mirror of
https://github.com/lowobservable/coax.git
synced 2026-01-12 00:43:00 +00:00
Add 3299 protocol support to interface2
This commit is contained in:
parent
14fd7485fe
commit
cec0ab781a
@ -28,6 +28,12 @@
|
||||
|
||||
#define COAX_ERROR_NOT_INITIALIZED -1024
|
||||
|
||||
enum class CoaxProtocol
|
||||
{
|
||||
_3270 = 0,
|
||||
_3299 = 1
|
||||
};
|
||||
|
||||
enum class CoaxParity
|
||||
{
|
||||
Odd = 0,
|
||||
@ -39,13 +45,17 @@ class SPICoaxTransceiver;
|
||||
class Coax
|
||||
{
|
||||
public:
|
||||
Coax(SPICoaxTransceiver &spiCoaxTransceiver, CoaxParity parity,
|
||||
volatile uint16_t *buffer, size_t bufferSize);
|
||||
Coax(SPICoaxTransceiver &spiCoaxTransceiver, volatile uint16_t *buffer,
|
||||
size_t bufferSize);
|
||||
|
||||
bool init();
|
||||
|
||||
void reset();
|
||||
|
||||
void setTXProtocol(CoaxProtocol protocol);
|
||||
void setRXProtocol(CoaxProtocol protocol);
|
||||
void setParity(CoaxParity parity);
|
||||
|
||||
int transmit(const uint16_t *buffer, size_t bufferCount);
|
||||
int receive(uint16_t *buffer, size_t bufferSize, uint16_t timeout);
|
||||
|
||||
@ -53,6 +63,8 @@ public:
|
||||
|
||||
private:
|
||||
SPICoaxTransceiver &_spiCoaxTransceiver;
|
||||
CoaxProtocol _txProtocol;
|
||||
CoaxProtocol _rxProtocol;
|
||||
CoaxParity _parity;
|
||||
|
||||
bool _isInitialized;
|
||||
@ -79,7 +91,9 @@ private:
|
||||
|
||||
#define COAX_REGISTER_CONTROL 0x2
|
||||
#define COAX_REGISTER_CONTROL_LOOPBACK 0x01
|
||||
#define COAX_REGISTER_CONTROL_TX_PROTOCOL 0x04
|
||||
#define COAX_REGISTER_CONTROL_TX_PARITY 0x08
|
||||
#define COAX_REGISTER_CONTROL_RX_PROTOCOL 0x20
|
||||
#define COAX_REGISTER_CONTROL_RX_PARITY 0x40
|
||||
|
||||
#define COAX_REGISTER_DEVICE_ID 0xf
|
||||
@ -100,7 +114,9 @@ public:
|
||||
int receive(uint16_t *buffer, size_t bufferSize);
|
||||
|
||||
void setLoopback(bool loopback);
|
||||
void setTXProtocol(CoaxProtocol protocol);
|
||||
void setTXParity(CoaxParity parity);
|
||||
void setRXProtocol(CoaxProtocol protocol);
|
||||
void setRXParity(CoaxParity parity);
|
||||
|
||||
inline bool isTXComplete()
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
#define INFO_MESSAGE_BUFFER_SIZE 0x06
|
||||
#define INFO_FEATURES 0x07
|
||||
|
||||
#define FEATURE_PROTOCOL_3299 0x10
|
||||
|
||||
#define TEST_SUPPORTED_TESTS 0x01
|
||||
|
||||
#define ERROR_INVALID_MESSAGE 1
|
||||
|
||||
@ -21,10 +21,12 @@
|
||||
|
||||
#include "coax.h"
|
||||
|
||||
Coax::Coax(SPICoaxTransceiver &spiCoaxTransceiver, CoaxParity parity,
|
||||
volatile uint16_t *buffer, size_t bufferSize) :
|
||||
Coax::Coax(SPICoaxTransceiver &spiCoaxTransceiver, volatile uint16_t *buffer,
|
||||
size_t bufferSize) :
|
||||
_spiCoaxTransceiver(spiCoaxTransceiver),
|
||||
_parity(parity),
|
||||
_txProtocol(CoaxProtocol::_3270),
|
||||
_rxProtocol(CoaxProtocol::_3270),
|
||||
_parity(CoaxParity::Even),
|
||||
_buffer(buffer),
|
||||
_bufferSize(bufferSize)
|
||||
{
|
||||
@ -41,7 +43,10 @@ bool Coax::init()
|
||||
return false;
|
||||
}
|
||||
|
||||
_spiCoaxTransceiver.setTXProtocol(_txProtocol);
|
||||
_spiCoaxTransceiver.setTXParity(_parity);
|
||||
|
||||
_spiCoaxTransceiver.setRXProtocol(_rxProtocol);
|
||||
_spiCoaxTransceiver.setRXParity(_parity);
|
||||
|
||||
_isInitialized = true;
|
||||
@ -59,10 +64,62 @@ void Coax::reset()
|
||||
|
||||
_spiCoaxTransceiver.reset();
|
||||
|
||||
_spiCoaxTransceiver.setTXProtocol(_txProtocol);
|
||||
_spiCoaxTransceiver.setTXParity(_parity);
|
||||
|
||||
_spiCoaxTransceiver.setRXProtocol(_rxProtocol);
|
||||
_spiCoaxTransceiver.setRXParity(_parity);
|
||||
}
|
||||
|
||||
void Coax::setTXProtocol(CoaxProtocol protocol)
|
||||
{
|
||||
if (!_isInitialized) {
|
||||
_txProtocol = protocol;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_txProtocol == protocol) {
|
||||
return;
|
||||
}
|
||||
|
||||
_spiCoaxTransceiver.setTXProtocol(protocol);
|
||||
|
||||
_txProtocol = protocol;
|
||||
}
|
||||
|
||||
void Coax::setRXProtocol(CoaxProtocol protocol)
|
||||
{
|
||||
if (!_isInitialized) {
|
||||
_rxProtocol = protocol;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_rxProtocol == protocol) {
|
||||
return;
|
||||
}
|
||||
|
||||
_spiCoaxTransceiver.setRXProtocol(protocol);
|
||||
|
||||
_rxProtocol = protocol;
|
||||
}
|
||||
|
||||
void Coax::setParity(CoaxParity parity)
|
||||
{
|
||||
if (!_isInitialized) {
|
||||
_parity = parity;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_parity == parity) {
|
||||
return;
|
||||
}
|
||||
|
||||
_spiCoaxTransceiver.setTXParity(parity);
|
||||
_spiCoaxTransceiver.setRXParity(parity);
|
||||
|
||||
_parity = parity;
|
||||
}
|
||||
|
||||
int Coax::transmit(const uint16_t *buffer, size_t bufferCount)
|
||||
{
|
||||
if (!_isInitialized) {
|
||||
@ -434,11 +491,21 @@ void SPICoaxTransceiver::setLoopback(bool loopback)
|
||||
writeRegister(COAX_REGISTER_CONTROL, loopback ? COAX_REGISTER_CONTROL_LOOPBACK : 0, COAX_REGISTER_CONTROL_LOOPBACK);
|
||||
}
|
||||
|
||||
void SPICoaxTransceiver::setTXProtocol(CoaxProtocol protocol)
|
||||
{
|
||||
writeRegister(COAX_REGISTER_CONTROL, protocol == CoaxProtocol::_3299 ? COAX_REGISTER_CONTROL_TX_PROTOCOL : 0, COAX_REGISTER_CONTROL_TX_PROTOCOL);
|
||||
}
|
||||
|
||||
void SPICoaxTransceiver::setTXParity(CoaxParity parity)
|
||||
{
|
||||
writeRegister(COAX_REGISTER_CONTROL, parity == CoaxParity::Even ? COAX_REGISTER_CONTROL_TX_PARITY : 0, COAX_REGISTER_CONTROL_TX_PARITY);
|
||||
}
|
||||
|
||||
void SPICoaxTransceiver::setRXProtocol(CoaxProtocol protocol)
|
||||
{
|
||||
writeRegister(COAX_REGISTER_CONTROL, protocol == CoaxProtocol::_3299 ? COAX_REGISTER_CONTROL_RX_PROTOCOL : 0, COAX_REGISTER_CONTROL_RX_PROTOCOL);
|
||||
}
|
||||
|
||||
void SPICoaxTransceiver::setRXParity(CoaxParity parity)
|
||||
{
|
||||
writeRegister(COAX_REGISTER_CONTROL, parity == CoaxParity::Even ? COAX_REGISTER_CONTROL_RX_PARITY : 0, COAX_REGISTER_CONTROL_RX_PARITY);
|
||||
|
||||
@ -46,6 +46,9 @@ Interface::Interface(Coax &coax, Indicators &indicators) :
|
||||
_coax(coax),
|
||||
_indicators(indicators)
|
||||
{
|
||||
_coax.setTXProtocol(CoaxProtocol::_3270);
|
||||
_coax.setRXProtocol(CoaxProtocol::_3270);
|
||||
_coax.setParity(CoaxParity::Even);
|
||||
}
|
||||
|
||||
void Interface::handleMessage(uint8_t *buffer, size_t bufferCount)
|
||||
@ -143,6 +146,12 @@ void Interface::handleTransmitReceive(uint8_t *buffer, size_t bufferCount)
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitBuffer[0] & 0x8000) {
|
||||
_coax.setTXProtocol(CoaxProtocol::_3299);
|
||||
} else {
|
||||
_coax.setTXProtocol(CoaxProtocol::_3270);
|
||||
}
|
||||
|
||||
int transmitCount = _coax.transmit(transmitBuffer, transmitBufferCount);
|
||||
|
||||
if (transmitCount < 0) {
|
||||
@ -214,8 +223,9 @@ void Interface::handleInfo(uint8_t *buffer, size_t bufferCount)
|
||||
buffer[2] = INFO_HARDWARE_TYPE;
|
||||
buffer[3] = INFO_FIRMWARE_VERSION;
|
||||
buffer[4] = INFO_MESSAGE_BUFFER_SIZE;
|
||||
buffer[5] = INFO_FEATURES;
|
||||
|
||||
MessageSender::send(buffer, 5);
|
||||
MessageSender::send(buffer, 6);
|
||||
} else if (query == INFO_HARDWARE_TYPE) {
|
||||
buffer[0] = 0x01;
|
||||
|
||||
@ -238,6 +248,11 @@ void Interface::handleInfo(uint8_t *buffer, size_t bufferCount)
|
||||
memcpy(buffer + 1, &size, sizeof(uint32_t));
|
||||
|
||||
MessageSender::send(buffer, 5);
|
||||
} else if (query == INFO_FEATURES) {
|
||||
buffer[0] = 0x01;
|
||||
buffer[1] = FEATURE_PROTOCOL_3299;
|
||||
|
||||
MessageSender::send(buffer, 2);
|
||||
} else {
|
||||
sendErrorMessage(ERROR_INVALID_MESSAGE, "HANDLE_INFO_UNKNOWN_QUERY");
|
||||
return;
|
||||
|
||||
@ -45,7 +45,7 @@ SPICoaxTransceiver spiCoaxTransceiver;
|
||||
|
||||
volatile uint16_t coaxBuffer[COAX_BUFFER_SIZE];
|
||||
|
||||
Coax coax(spiCoaxTransceiver, CoaxParity::Even, coaxBuffer, COAX_BUFFER_SIZE);
|
||||
Coax coax(spiCoaxTransceiver, coaxBuffer, COAX_BUFFER_SIZE);
|
||||
|
||||
volatile uint8_t messageBuffer[MESSAGE_BUFFER_SIZE];
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ module coax_buffered_rx (
|
||||
input read_strobe,
|
||||
output empty,
|
||||
output full,
|
||||
input protocol,
|
||||
input parity
|
||||
);
|
||||
parameter CLOCKS_PER_BIT = 8;
|
||||
@ -45,6 +46,7 @@ module coax_buffered_rx (
|
||||
.error(coax_rx_error),
|
||||
.data(coax_rx_data),
|
||||
.strobe(coax_rx_strobe),
|
||||
.protocol(protocol),
|
||||
.parity(parity)
|
||||
);
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ module coax_buffered_tx (
|
||||
output empty,
|
||||
output full,
|
||||
output reg ready,
|
||||
input protocol,
|
||||
input parity
|
||||
);
|
||||
parameter CLOCKS_PER_BIT = 8;
|
||||
@ -56,6 +57,7 @@ module coax_buffered_tx (
|
||||
.data(coax_tx_data),
|
||||
.strobe(coax_tx_strobe),
|
||||
.ready(coax_tx_ready),
|
||||
.protocol(protocol),
|
||||
.parity(parity)
|
||||
);
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ module coax_rx (
|
||||
output reg error,
|
||||
output reg [9:0] data,
|
||||
output reg strobe = 0,
|
||||
input protocol,
|
||||
input parity
|
||||
);
|
||||
parameter CLOCKS_PER_BIT = 8;
|
||||
@ -95,6 +96,8 @@ module coax_rx (
|
||||
case (state)
|
||||
STATE_IDLE:
|
||||
begin
|
||||
next_input_data = 10'b0;
|
||||
|
||||
if (ss_detector_strobe)
|
||||
begin
|
||||
// The start sequence ends with a code violation, so reset
|
||||
@ -111,7 +114,7 @@ module coax_rx (
|
||||
// differently and consider it part of the start sequence as
|
||||
// it must be a 1 and we don't consider the receiver active
|
||||
// until this has been detected.
|
||||
next_bit_counter = 0;
|
||||
next_bit_counter = (protocol == 1 ? 4 : 0);
|
||||
|
||||
if (rx != previous_rx && mid_bit_counter > CLOCKS_PER_HALF_BIT)
|
||||
begin
|
||||
|
||||
@ -22,6 +22,7 @@ module coax_tx (
|
||||
input [9:0] data,
|
||||
input strobe,
|
||||
output ready,
|
||||
input protocol,
|
||||
input parity
|
||||
);
|
||||
parameter CLOCKS_PER_BIT = 8;
|
||||
@ -48,6 +49,8 @@ module coax_tx (
|
||||
|
||||
reg next_tx;
|
||||
|
||||
reg first_word;
|
||||
reg next_first_word;
|
||||
reg end_sequence;
|
||||
reg next_end_sequence;
|
||||
|
||||
@ -86,6 +89,7 @@ module coax_tx (
|
||||
|
||||
next_tx = 0;
|
||||
|
||||
next_first_word = first_word;
|
||||
next_end_sequence = 0;
|
||||
|
||||
next_output_data = output_data;
|
||||
@ -188,6 +192,7 @@ module coax_tx (
|
||||
START_SEQUENCE_9:
|
||||
begin
|
||||
next_tx = 1;
|
||||
next_first_word = 1;
|
||||
|
||||
if (last_clock)
|
||||
next_state = SYNC_BIT;
|
||||
@ -197,10 +202,21 @@ module coax_tx (
|
||||
begin
|
||||
next_tx = first_half ? 0 : 1;
|
||||
|
||||
next_bit_counter = 9;
|
||||
|
||||
if (last_clock)
|
||||
begin
|
||||
// First word is 6 bits in 3299 protocol mode.
|
||||
if (protocol == 1 && first_word)
|
||||
begin
|
||||
next_output_data = { output_data[5:0], 4'b0 };
|
||||
next_bit_counter = 5;
|
||||
end
|
||||
else
|
||||
begin
|
||||
next_bit_counter = 9;
|
||||
end
|
||||
|
||||
next_state = DATA_BIT;
|
||||
end
|
||||
end
|
||||
|
||||
DATA_BIT:
|
||||
@ -228,6 +244,8 @@ module coax_tx (
|
||||
|
||||
if (last_clock)
|
||||
begin
|
||||
next_first_word = 0;
|
||||
|
||||
if (output_data_full)
|
||||
begin
|
||||
next_state = SYNC_BIT;
|
||||
@ -280,6 +298,7 @@ module coax_tx (
|
||||
active <= (state != IDLE); // TODO: this causes active to remain high one additional clock cycle
|
||||
tx <= next_tx;
|
||||
|
||||
first_word <= next_first_word;
|
||||
end_sequence <= next_end_sequence;
|
||||
|
||||
output_data <= next_output_data;
|
||||
|
||||
@ -36,6 +36,7 @@ module control (
|
||||
input tx_empty,
|
||||
input tx_full,
|
||||
input tx_ready,
|
||||
output tx_protocol,
|
||||
output tx_parity,
|
||||
|
||||
// RX
|
||||
@ -45,6 +46,7 @@ module control (
|
||||
input [9:0] rx_data,
|
||||
output reg rx_read_strobe,
|
||||
input rx_empty,
|
||||
output rx_protocol,
|
||||
output rx_parity
|
||||
);
|
||||
parameter DEFAULT_CONTROL_REGISTER = 8'b01001000;
|
||||
@ -342,6 +344,8 @@ module control (
|
||||
|
||||
assign loopback = control_register[0];
|
||||
|
||||
assign tx_protocol = control_register[2];
|
||||
assign tx_parity = control_register[3];
|
||||
assign rx_protocol = control_register[5];
|
||||
assign rx_parity = control_register[6];
|
||||
endmodule
|
||||
|
||||
@ -98,6 +98,7 @@ module top (
|
||||
wire tx_empty;
|
||||
wire tx_full;
|
||||
wire tx_ready;
|
||||
wire tx_protocol;
|
||||
wire tx_parity;
|
||||
|
||||
coax_buffered_tx #(
|
||||
@ -115,6 +116,7 @@ module top (
|
||||
.empty(tx_empty),
|
||||
.full(tx_full),
|
||||
.ready(tx_ready),
|
||||
.protocol(tx_protocol),
|
||||
.parity(tx_parity)
|
||||
);
|
||||
|
||||
@ -125,6 +127,7 @@ module top (
|
||||
wire [9:0] rx_data;
|
||||
wire rx_read_strobe;
|
||||
wire rx_empty;
|
||||
wire rx_protocol;
|
||||
wire rx_parity;
|
||||
|
||||
coax_buffered_rx #(
|
||||
@ -139,6 +142,7 @@ module top (
|
||||
.data(rx_data),
|
||||
.read_strobe(rx_read_strobe),
|
||||
.empty(rx_empty),
|
||||
.protocol(rx_protocol),
|
||||
.parity(rx_parity)
|
||||
);
|
||||
|
||||
@ -184,6 +188,7 @@ module top (
|
||||
.tx_empty(tx_empty),
|
||||
.tx_full(tx_full),
|
||||
.tx_ready(tx_ready),
|
||||
.tx_protocol(tx_protocol),
|
||||
.tx_parity(tx_parity),
|
||||
|
||||
.rx_reset(rx_reset),
|
||||
@ -192,6 +197,7 @@ module top (
|
||||
.rx_data(rx_data),
|
||||
.rx_read_strobe(rx_read_strobe),
|
||||
.rx_empty(rx_empty),
|
||||
.rx_protocol(rx_protocol),
|
||||
.rx_parity(rx_parity)
|
||||
);
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ coax_tx_tb: coax_tx_tb.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v
|
||||
coax_rx_blanker_tb: coax_rx_blanker_tb.v $(RTL)/coax_rx_blanker.v
|
||||
coax_tx_rx_frontend_tb: coax_tx_rx_frontend_tb.v $(RTL)/coax_tx_rx_frontend.v $(RTL)/coax_tx_distorter.v $(RTL)/coax_rx_blanker.v
|
||||
control_tb: control_tb.v $(RTL)/control.v $(RTL)/coax_buffered_tx.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v $(RTL)/coax_buffer.v $(RTL)/third_party/*.v
|
||||
tx_rx_loopback_tb: tx_rx_loopback_tb.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v $(RTL)/coax_rx.v $(RTL)/coax_rx_ss_detector.v
|
||||
regression_memorex_tb: regression_memorex_tb.v $(RTL)/coax_rx.v $(RTL)/coax_rx_ss_detector.v
|
||||
|
||||
test: $(TESTS)
|
||||
|
||||
@ -31,6 +31,7 @@ module coax_buffered_rx_tb;
|
||||
.reset(reset),
|
||||
.rx(rx),
|
||||
.read_strobe(read_strobe),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ module coax_buffered_tx_tb;
|
||||
.data(data),
|
||||
.load_strobe(load_strobe),
|
||||
.start_strobe(start_strobe),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ module coax_rx_tb;
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.rx(rx),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ module coax_tx_tb;
|
||||
.reset(reset),
|
||||
.data(data),
|
||||
.strobe(strobe),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ module regression_memorex_tb;
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.rx(rx),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
323
interface2/fpga/tests/tx_rx_loopback_tb.v
Normal file
323
interface2/fpga/tests/tx_rx_loopback_tb.v
Normal file
@ -0,0 +1,323 @@
|
||||
`default_nettype none
|
||||
|
||||
`include "assert.v"
|
||||
|
||||
module tx_rx_loopback_tb;
|
||||
reg clk = 0;
|
||||
|
||||
initial
|
||||
begin
|
||||
forever
|
||||
begin
|
||||
#1 clk <= ~clk;
|
||||
end
|
||||
end
|
||||
|
||||
reg reset = 0;
|
||||
wire loopback;
|
||||
wire tx_active;
|
||||
reg [9:0] tx_data;
|
||||
reg tx_strobe = 0;
|
||||
wire tx_ready;
|
||||
reg tx_protocol = 0;
|
||||
reg tx_parity = 0;
|
||||
wire rx_error;
|
||||
wire [9:0] rx_data;
|
||||
wire rx_strobe;
|
||||
reg rx_protocol = 0;
|
||||
reg rx_parity = 0;
|
||||
|
||||
coax_tx #(
|
||||
.CLOCKS_PER_BIT(8)
|
||||
) dut_tx (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.active(tx_active),
|
||||
.tx(loopback),
|
||||
.data(tx_data),
|
||||
.strobe(tx_strobe),
|
||||
.ready(tx_ready),
|
||||
.protocol(tx_protocol),
|
||||
.parity(tx_parity)
|
||||
);
|
||||
|
||||
coax_rx #(
|
||||
.CLOCKS_PER_BIT(8)
|
||||
) dut_rx (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.rx(loopback),
|
||||
.error(rx_error),
|
||||
.data(rx_data),
|
||||
.strobe(rx_strobe),
|
||||
.protocol(rx_protocol),
|
||||
.parity(rx_parity)
|
||||
);
|
||||
|
||||
initial
|
||||
begin
|
||||
$dumpfile("tx_rx_loopback_tb.vcd");
|
||||
$dumpvars(0, tx_rx_loopback_tb);
|
||||
|
||||
test_3270_protocol;
|
||||
test_3299_protocol;
|
||||
test_protocol_mismatch;
|
||||
test_parity_mismatch;
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
task test_3270_protocol;
|
||||
begin
|
||||
$display("START: test_3270_protocol");
|
||||
|
||||
tx_protocol = 0;
|
||||
tx_parity = 1;
|
||||
rx_protocol = 0;
|
||||
rx_parity = 1;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
fork: test_3270_protocol_tx_rx_fork
|
||||
begin
|
||||
tx_data = 10'b0101110101;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
@(posedge tx_ready);
|
||||
|
||||
tx_data = 10'b1010001010;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
end
|
||||
|
||||
begin
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b0101110101, "RX data should be equal to TX data");
|
||||
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b1010001010, "RX data should be equal to TX data");
|
||||
|
||||
disable test_3270_protocol_tx_rx_fork;
|
||||
end
|
||||
|
||||
begin
|
||||
#1000;
|
||||
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
|
||||
disable test_3270_protocol_tx_rx_fork;
|
||||
end
|
||||
join
|
||||
|
||||
#100;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
$display("END: test_3270_protocol");
|
||||
end
|
||||
endtask
|
||||
|
||||
task test_3299_protocol;
|
||||
begin
|
||||
$display("START: test_3299_protocol");
|
||||
|
||||
tx_protocol = 1;
|
||||
tx_parity = 1;
|
||||
rx_protocol = 1;
|
||||
rx_parity = 1;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
fork: test_3299_protocol_tx_rx_fork
|
||||
begin
|
||||
tx_data = 10'b0000110001;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
@(posedge tx_ready);
|
||||
|
||||
tx_data = 10'b0101110101;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
@(posedge tx_ready);
|
||||
|
||||
tx_data = 10'b1010001010;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
end
|
||||
|
||||
begin
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b0000110001, "RX data should be equal to TX data");
|
||||
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b0101110101, "RX data should be equal to TX data");
|
||||
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b1010001010, "RX data should be equal to TX data");
|
||||
|
||||
disable test_3299_protocol_tx_rx_fork;
|
||||
end
|
||||
|
||||
begin
|
||||
#1000;
|
||||
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
|
||||
disable test_3299_protocol_tx_rx_fork;
|
||||
end
|
||||
join
|
||||
|
||||
#100;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
$display("END: test_3299_protocol");
|
||||
end
|
||||
endtask
|
||||
|
||||
task test_protocol_mismatch;
|
||||
begin
|
||||
$display("START: test_protocol_mismatch");
|
||||
|
||||
tx_protocol = 1;
|
||||
tx_parity = 1;
|
||||
rx_protocol = 0;
|
||||
rx_parity = 1;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
fork: test_protocol_mismatch_tx_rx_fork
|
||||
begin
|
||||
tx_data = 10'b0000110001;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
@(posedge tx_ready);
|
||||
|
||||
tx_data = 10'b0101110101;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
// Wait for TX to complete... we don't want to reset the RX
|
||||
// to soon as it could be reactivated with the remaining
|
||||
// transmission.
|
||||
@(negedge tx_active);
|
||||
|
||||
disable test_protocol_mismatch_tx_rx_fork;
|
||||
end
|
||||
|
||||
begin
|
||||
#1000;
|
||||
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
|
||||
disable test_protocol_mismatch_tx_rx_fork;
|
||||
end
|
||||
join
|
||||
|
||||
// The exact error (parity or loss of mid-bit transition) may depend
|
||||
// on the length of message and data.
|
||||
`assert_high(rx_error, "RX error should be HIGH");
|
||||
`assert_equal(rx_data, dut_rx.ERROR_LOSS_OF_MID_BIT_TRANSITION, "RX data should be ERROR_LOSS_OF_MID_BIT_TRANSITION");
|
||||
|
||||
#16;
|
||||
|
||||
dut_reset;
|
||||
|
||||
#100;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
$display("END: test_protocol_mismatch");
|
||||
end
|
||||
endtask
|
||||
|
||||
task test_parity_mismatch;
|
||||
begin
|
||||
$display("START: test_parity_mismatch");
|
||||
|
||||
tx_protocol = 0;
|
||||
tx_parity = 1;
|
||||
rx_protocol = 0;
|
||||
rx_parity = 0;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
fork: test_parity_mismatch_tx_rx_fork
|
||||
begin
|
||||
tx_data = 10'b0101110101;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
// Wait for TX to complete... we don't want to reset the RX
|
||||
// to soon as it could be reactivated with the remaining
|
||||
// transmission.
|
||||
@(negedge tx_active);
|
||||
|
||||
disable test_parity_mismatch_tx_rx_fork;
|
||||
end
|
||||
|
||||
begin
|
||||
#1000;
|
||||
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
|
||||
disable test_parity_mismatch_tx_rx_fork;
|
||||
end
|
||||
join
|
||||
|
||||
`assert_high(rx_error, "RX error should be HIGH");
|
||||
`assert_equal(rx_data, dut_rx.ERROR_PARITY, "RX data should be ERROR_PARITY");
|
||||
|
||||
#16;
|
||||
|
||||
dut_reset;
|
||||
|
||||
#100;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
$display("END: test_parity_mismatch");
|
||||
end
|
||||
endtask
|
||||
|
||||
task dut_reset;
|
||||
begin
|
||||
reset = 1;
|
||||
#2;
|
||||
reset = 0;
|
||||
end
|
||||
endtask
|
||||
endmodule
|
||||
833
protocol/3299.svg
Normal file
833
protocol/3299.svg
Normal file
@ -0,0 +1,833 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="800"
|
||||
height="152"
|
||||
viewBox="0 0 211.667 40.217"
|
||||
version="1.1"
|
||||
id="svg271"
|
||||
sodipodi:docname="3299.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview273"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="true"
|
||||
inkscape:zoom="3.6928652"
|
||||
inkscape:cx="535.49206"
|
||||
inkscape:cy="112.10807"
|
||||
inkscape:window-width="3834"
|
||||
inkscape:window-height="2154"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g269">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1114"
|
||||
units="px"
|
||||
spacingx="0.26458375"
|
||||
spacingy="0.26458553"
|
||||
dotted="true"
|
||||
empspacing="8" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs23">
|
||||
<marker
|
||||
overflow="visible"
|
||||
id="g"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<path
|
||||
stroke-width=".4pt"
|
||||
stroke="#999"
|
||||
fill-rule="evenodd"
|
||||
fill="#999"
|
||||
d="M2.308 0l-3.46 2v-4z"
|
||||
id="path2" />
|
||||
</marker>
|
||||
<marker
|
||||
overflow="visible"
|
||||
id="f"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<path
|
||||
stroke-width=".4pt"
|
||||
stroke="#999"
|
||||
fill-rule="evenodd"
|
||||
fill="#999"
|
||||
d="M-2.308 0l3.46-2v4z"
|
||||
id="path5" />
|
||||
</marker>
|
||||
<marker
|
||||
overflow="visible"
|
||||
id="e"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<path
|
||||
stroke-width=".4pt"
|
||||
stroke="#999"
|
||||
fill-rule="evenodd"
|
||||
fill="#999"
|
||||
d="M2.308 0l-3.46 2v-4z"
|
||||
id="path8" />
|
||||
</marker>
|
||||
<marker
|
||||
overflow="visible"
|
||||
id="d"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<path
|
||||
stroke-width=".4pt"
|
||||
stroke="#999"
|
||||
fill-rule="evenodd"
|
||||
fill="#999"
|
||||
d="M-2.308 0l3.46-2v4z"
|
||||
id="path11" />
|
||||
</marker>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
height="1.0104658"
|
||||
y="-0.0052328963"
|
||||
width="1.0035491"
|
||||
x="-0.0017745273"
|
||||
id="b">
|
||||
<feGaussianBlur
|
||||
stdDeviation=".018"
|
||||
id="feGaussianBlur14" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
id="c"
|
||||
x="-0.0014912155"
|
||||
width="1.0029824"
|
||||
y="-0.0020151678"
|
||||
height="1.0040303">
|
||||
<feGaussianBlur
|
||||
stdDeviation=".018"
|
||||
id="feGaussianBlur17" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
height="1.0417323"
|
||||
y="-0.020866141"
|
||||
width="1.0376163"
|
||||
x="-0.018808143"
|
||||
id="a">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur20" />
|
||||
</filter>
|
||||
<marker
|
||||
overflow="visible"
|
||||
id="e-1"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<path
|
||||
stroke-width="0.4pt"
|
||||
stroke="#999999"
|
||||
fill-rule="evenodd"
|
||||
fill="#999999"
|
||||
d="m 2.308,0 -3.46,2 v -4 z"
|
||||
id="path8-7" />
|
||||
</marker>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
height="1.0090845"
|
||||
y="-0.0045422457"
|
||||
width="1.0011981"
|
||||
x="-0.00059902789"
|
||||
id="b-1">
|
||||
<feGaussianBlur
|
||||
stdDeviation=".018"
|
||||
id="feGaussianBlur14-1" />
|
||||
</filter>
|
||||
</defs>
|
||||
<path
|
||||
d="M4.233 14.817H12.7v12.7H4.233z"
|
||||
fill="#aef"
|
||||
id="path25" />
|
||||
<path
|
||||
d="M12.7 14.817h8.467v12.7H12.7z"
|
||||
fill="#d5f6ff"
|
||||
id="path27" />
|
||||
<path
|
||||
d="M21.167 14.817h8.467v12.7h-8.467z"
|
||||
fill="#aef"
|
||||
id="path29" />
|
||||
<path
|
||||
d="M29.633 14.817H38.1v12.7h-8.467z"
|
||||
fill="#d5f6ff"
|
||||
id="path31" />
|
||||
<path
|
||||
d="M38.1 14.817h8.467v12.7H38.1z"
|
||||
fill="#aef"
|
||||
id="path33" />
|
||||
<path
|
||||
d="M46.567 14.817h8.467v12.7h-8.467z"
|
||||
fill="#d5f6ff"
|
||||
id="path35" />
|
||||
<path
|
||||
d="M55.033 14.817H63.5v12.7h-8.467z"
|
||||
fill="#aef"
|
||||
id="path37" />
|
||||
<path
|
||||
d="m 80.432843,14.81679 h 8.467006 v 12.7 h -8.467006 z"
|
||||
fill="#d5f6ff"
|
||||
id="path47" />
|
||||
<path
|
||||
d="m 88.899849,14.81679 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#aaeeff"
|
||||
id="path49" />
|
||||
<path
|
||||
d="m 97.365849,14.81679 h 8.467001 v 12.7 h -8.467001 z"
|
||||
fill="#d5f6ff"
|
||||
id="path51" />
|
||||
<path
|
||||
d="m 105.83285,14.81679 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#aaeeff"
|
||||
id="path53" />
|
||||
<path
|
||||
d="m 114.29985,14.81679 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#d5f6ff"
|
||||
id="path55" />
|
||||
<path
|
||||
d="m 122.76585,14.81679 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#aaeeff"
|
||||
id="path57" />
|
||||
<path
|
||||
d="m 131.23285,14.81679 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#d5f6ff"
|
||||
id="path59" />
|
||||
<path
|
||||
d="m 139.69985,14.81679 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#aaeeff"
|
||||
id="path61" />
|
||||
<path
|
||||
d="m 148.16585,14.81679 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#d5f6ff"
|
||||
id="path63" />
|
||||
<path
|
||||
d="m 156.63285,14.81679 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#aaeeff"
|
||||
id="path65" />
|
||||
<path
|
||||
d="m 63.499816,14.81679 h 8.467011 v 12.7 h -8.467011 z m 101.600034,0 h 8.467 v 12.7 h -8.467 z"
|
||||
fill="#d5f6ff"
|
||||
id="path67" />
|
||||
<path
|
||||
d="M2.117 14.817h2.117v12.7H2.117z"
|
||||
fill="#ffd5e5"
|
||||
id="path69" />
|
||||
<path
|
||||
d="m 207.43403,14.81679 h 2.117 v 12.7 h -2.117 z"
|
||||
fill="#ffaacc"
|
||||
id="path71" />
|
||||
<path
|
||||
d="m 71.965827,14.81679 h 8.467016 v 12.7 h -8.467016 z"
|
||||
fill="#aaeeff"
|
||||
id="path73" />
|
||||
<g
|
||||
filter="url(#a)"
|
||||
id="g269">
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="m 63.499816,34.92479 2.116,-3.175 h 4.234007 l 2.116004,3.175 -2.116004,3.175 h -4.234007 z"
|
||||
id="path229" />
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="M 4.233,10.583 V 2.117 M 12.7,10.583 V 2.117 m 50.799816,8.466421 V 2.1174212"
|
||||
id="path75"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<text
|
||||
filter="url(#b)"
|
||||
text-anchor="middle"
|
||||
font-family="sans-serif"
|
||||
font-size="10.667"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
x="11.469"
|
||||
y="7.917"
|
||||
transform="rotate(-90 7.523 1.868) scale(.26458)"
|
||||
id="text81"><tspan
|
||||
x="11.469"
|
||||
y="7.917"
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
id="tspan77">Sync</tspan><tspan
|
||||
x="11.469"
|
||||
y="21.25"
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
id="tspan79">Bit</tspan></text>
|
||||
<text
|
||||
filter="url(#c)"
|
||||
text-anchor="middle"
|
||||
font-family="sans-serif"
|
||||
font-size="10.667px"
|
||||
font-weight="400"
|
||||
transform="matrix(0,-0.26458,0.26458,0,64.945816,10.09279)"
|
||||
y="7.9169998"
|
||||
x="13.781"
|
||||
style="line-height:1.25;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
id="text87"><tspan
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
y="7.9169998"
|
||||
x="13.781"
|
||||
id="tspan83">Parity</tspan><tspan
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
y="21.25"
|
||||
x="13.781"
|
||||
id="tspan85">Bit</tspan></text>
|
||||
<text
|
||||
filter="url(#b)"
|
||||
font-family="sans-serif"
|
||||
font-size="10.667px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="-0.70300001"
|
||||
y="7.9169998"
|
||||
transform="matrix(0.26458,0,0,0.26458,27.410186,5.141)"
|
||||
id="text91"><tspan
|
||||
x="-0.70300001"
|
||||
y="7.9169998"
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan89">Address (6-bits)</tspan></text>
|
||||
<path
|
||||
marker-end="url(#e)"
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="M 50.799711,6.3500527 H 62.441474"
|
||||
id="path95"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
marker-end="url(#e-1)"
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="M 25.3995,6.3500527 H 13.757737"
|
||||
id="path95-7"
|
||||
sodipodi:nodetypes="cc"
|
||||
style="marker-end:url(#e-1)" />
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="M 71.965827,10.58279 V 2.1167897 M 80.432843,10.58279 V 2.1167897 M 165.09985,10.58279 V 2.1167897 m 8.466,8.4660003 V 2.1167897"
|
||||
id="path97" />
|
||||
<text
|
||||
filter="url(#b)"
|
||||
text-anchor="middle"
|
||||
font-family="sans-serif"
|
||||
font-size="10.667px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
x="11.469"
|
||||
y="7.9169998"
|
||||
transform="matrix(0,-0.26458,0.26458,0,73.387829,9.3897897)"
|
||||
id="text103"><tspan
|
||||
x="11.469"
|
||||
y="7.9169998"
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
id="tspan99">Sync</tspan><tspan
|
||||
x="11.469"
|
||||
y="21.25"
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
id="tspan101">Bit</tspan></text>
|
||||
<text
|
||||
filter="url(#c)"
|
||||
text-anchor="middle"
|
||||
font-family="sans-serif"
|
||||
font-size="10.667px"
|
||||
font-weight="400"
|
||||
transform="matrix(0,-0.26458,0.26458,0,166.54585,10.09279)"
|
||||
y="7.9169998"
|
||||
x="13.781"
|
||||
style="line-height:1.25;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
id="text109"><tspan
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
y="7.9169998"
|
||||
x="13.781"
|
||||
id="tspan105">Parity</tspan><tspan
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center"
|
||||
y="21.25"
|
||||
x="13.781"
|
||||
id="tspan107">Bit</tspan></text>
|
||||
<text
|
||||
filter="url(#b)"
|
||||
font-family="sans-serif"
|
||||
font-size="10.667px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="-0.70300001"
|
||||
y="7.9169998"
|
||||
transform="matrix(0.26458,0,0,0.26458,113.13485,5.1407897)"
|
||||
id="text113"><tspan
|
||||
x="-0.70300001"
|
||||
y="7.9169998"
|
||||
style="-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan111">Data (10-bits)</tspan></text>
|
||||
<path
|
||||
marker-start="url(#f)"
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="M 81.490845,6.3497897 H 111.12485"
|
||||
id="path115" />
|
||||
<path
|
||||
marker-end="url(#g)"
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="m 134.40785,6.3497897 h 29.633"
|
||||
id="path117" />
|
||||
<path
|
||||
stroke-width=".265"
|
||||
stroke="#000"
|
||||
fill="none"
|
||||
d="M21.167 34.925l2.116-3.175h4.234l2.116 3.175-2.116 3.175h-4.234z"
|
||||
id="path119" />
|
||||
<text
|
||||
transform="translate(0,-1.058)"
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="24.131001"
|
||||
y="37.497002"
|
||||
id="text123"><tspan
|
||||
x="24.131001"
|
||||
y="37.497002"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan121">1</tspan></text>
|
||||
<path
|
||||
stroke-width=".265"
|
||||
stroke="#000"
|
||||
fill="none"
|
||||
d="M29.633 34.925l2.117-3.175h4.233l2.117 3.175-2.117 3.175H31.75z"
|
||||
id="path125" />
|
||||
<text
|
||||
transform="translate(8.467,-1.058)"
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="24.131001"
|
||||
y="37.497002"
|
||||
id="text129"><tspan
|
||||
x="24.131001"
|
||||
y="37.497002"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan127">1</tspan></text>
|
||||
<path
|
||||
stroke-width=".265"
|
||||
stroke="#000"
|
||||
fill="none"
|
||||
d="M38.1 34.925l2.117-3.175h4.233l2.117 3.175L44.45 38.1h-4.233z"
|
||||
id="path131" />
|
||||
<text
|
||||
transform="translate(16.933 -1.058)"
|
||||
stroke-width=".265"
|
||||
font-family="monospace"
|
||||
font-size="4.233"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="24.131"
|
||||
y="37.497"
|
||||
id="text135"><tspan
|
||||
x="24.131"
|
||||
y="37.497"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan133">0</tspan></text>
|
||||
<path
|
||||
stroke-width=".265"
|
||||
stroke="#000"
|
||||
fill="none"
|
||||
d="M46.567 34.925l2.116-3.175h4.234l2.116 3.175-2.116 3.175h-4.234z"
|
||||
id="path149" />
|
||||
<text
|
||||
transform="translate(25.4,-1.058)"
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
y="37.497002"
|
||||
x="24.131001"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text153"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="37.497002"
|
||||
x="24.131001"
|
||||
id="tspan151">0</tspan></text>
|
||||
<path
|
||||
stroke-width=".265"
|
||||
stroke="#000"
|
||||
fill="none"
|
||||
d="M55.033 34.925l2.117-3.175h4.233l2.117 3.175-2.117 3.175H57.15z"
|
||||
id="path155" />
|
||||
<text
|
||||
transform="translate(33.867,-1.058)"
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="24.131001"
|
||||
y="37.497002"
|
||||
id="text159"><tspan
|
||||
x="24.131001"
|
||||
y="37.497002"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan157">0</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 88.899849,34.92479 2.116,-3.175 h 4.234 l 2.116,3.175 -2.116,3.175 h -4.234 z"
|
||||
id="path167" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
y="36.438793"
|
||||
x="91.863678"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text171"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="36.438793"
|
||||
x="91.863678"
|
||||
id="tspan169">0</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 105.83285,34.92479 2.117,-3.175 h 4.233 l 2.117,3.175 -2.117,3.175 h -4.233 z"
|
||||
id="path173" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
y="36.438793"
|
||||
x="108.79669"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text177"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="36.438793"
|
||||
x="108.79669"
|
||||
id="tspan175">0</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 131.23285,34.92479 2.117,-3.175 h 4.233 l 2.117,3.175 -2.117,3.175 h -4.233 z"
|
||||
id="path179" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
y="36.438793"
|
||||
x="134.1967"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text183"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="36.438793"
|
||||
x="134.1967"
|
||||
id="tspan181">0</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 97.365849,34.92479 2.117,-3.175 h 4.233001 l 2.117,3.175 -2.117,3.175 h -4.233001 z"
|
||||
id="path185" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
y="36.438793"
|
||||
x="100.33068"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text189"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="36.438793"
|
||||
x="100.33068"
|
||||
id="tspan187">1</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 148.16585,34.92479 2.117,-3.175 h 4.233 l 2.117,3.175 -2.117,3.175 h -4.233 z"
|
||||
id="path191" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
y="36.438793"
|
||||
x="151.13069"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text195"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="36.438793"
|
||||
x="151.13069"
|
||||
id="tspan193">1</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 139.69985,34.92479 2.116,-3.175 h 4.234 l 2.116,3.175 -2.116,3.175 h -4.234 z"
|
||||
id="path197" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="142.6637"
|
||||
y="36.438793"
|
||||
id="text201"><tspan
|
||||
x="142.6637"
|
||||
y="36.438793"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan199">0</tspan></text>
|
||||
<g
|
||||
filter="url(#a)"
|
||||
transform="translate(93.132849,-1.0582103)"
|
||||
stroke-width="0.265"
|
||||
id="g209">
|
||||
<path
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 21.167,35.983 2.116,-3.175 h 4.234 l 2.116,3.175 -2.116,3.175 h -4.234 z"
|
||||
id="path203" />
|
||||
<text
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="24.131001"
|
||||
y="37.497002"
|
||||
id="text207"><tspan
|
||||
x="24.131001"
|
||||
y="37.497002"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan205">0</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 122.76585,34.92479 2.117,-3.175 h 4.233 l 2.117,3.175 -2.117,3.175 h -4.233 z"
|
||||
id="path211" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="125.7307"
|
||||
y="36.438793"
|
||||
id="text215"><tspan
|
||||
x="125.7307"
|
||||
y="36.438793"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan213">0</tspan></text>
|
||||
<path
|
||||
stroke-width=".265"
|
||||
stroke="#999"
|
||||
fill="none"
|
||||
d="M4.233 34.925L6.35 31.75h4.233l2.117 3.175-2.117 3.175H6.35z"
|
||||
id="path217" />
|
||||
<text
|
||||
fill="#999"
|
||||
transform="translate(-16.933 -1.058)"
|
||||
stroke-width=".265"
|
||||
font-family="monospace"
|
||||
font-size="4.233"
|
||||
font-weight="400"
|
||||
y="37.497"
|
||||
x="24.131"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text221"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="37.497"
|
||||
x="24.131"
|
||||
id="tspan219">1</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="m 71.965827,34.92479 2.117004,-3.175 h 4.233008 l 2.117004,3.175 -2.117004,3.175 h -4.233008 z"
|
||||
id="path223" />
|
||||
<text
|
||||
fill="#999999"
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="74.930679"
|
||||
y="36.438793"
|
||||
id="text227"><tspan
|
||||
x="74.930679"
|
||||
y="36.438793"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan225">1</tspan></text>
|
||||
<text
|
||||
fill="#999999"
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="66.463692"
|
||||
y="36.438793"
|
||||
id="text233"><tspan
|
||||
x="66.463692"
|
||||
y="36.438793"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan231">0</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#999999"
|
||||
fill="none"
|
||||
d="m 165.09985,34.92479 2.116,-3.175 h 4.234 l 2.116,3.175 -2.116,3.175 h -4.234 z"
|
||||
id="path235" />
|
||||
<text
|
||||
fill="#999999"
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
y="36.438793"
|
||||
x="168.06369"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text239"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="36.438793"
|
||||
x="168.06369"
|
||||
id="tspan237">0</tspan></text>
|
||||
<path
|
||||
stroke-width=".265"
|
||||
stroke="#000"
|
||||
fill="none"
|
||||
d="M12.7 34.925l2.117-3.175h4.233l2.117 3.175L19.05 38.1h-4.233z"
|
||||
id="path241" />
|
||||
<text
|
||||
transform="translate(-8.467,-1.058)"
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
y="37.497002"
|
||||
x="24.131001"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="text245"><tspan
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
y="37.497002"
|
||||
x="24.131001"
|
||||
id="tspan243">1</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 80.432843,34.92479 2.117004,-3.175 h 4.233002 l 2.117,3.175 -2.117,3.175 h -4.233002 z"
|
||||
id="path253" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="83.396683"
|
||||
y="36.438793"
|
||||
id="text257"><tspan
|
||||
x="83.396683"
|
||||
y="36.438793"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan255">1</tspan></text>
|
||||
<path
|
||||
stroke-width="0.265"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 156.63285,34.92479 2.117,-3.175 h 4.233 l 2.117,3.175 -2.117,3.175 h -4.233 z"
|
||||
id="path259" />
|
||||
<text
|
||||
stroke-width="0.265"
|
||||
font-family="monospace"
|
||||
font-size="4.233px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
x="159.59669"
|
||||
y="36.438793"
|
||||
id="text263"><tspan
|
||||
x="159.59669"
|
||||
y="36.438793"
|
||||
style="-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
|
||||
id="tspan261">0</tspan></text>
|
||||
<path
|
||||
stroke-width=".216"
|
||||
stroke="#b3b3b3"
|
||||
fill="none"
|
||||
d="M12.7 11.642v2.116m8.467-2.116v2.116m8.466-2.116v2.116m8.467-2.116v2.116m8.467-2.116v2.116m8.466-2.116v2.116m8.467-2.116v2.116m8.467-2.116v2.116m8.466-2.116v2.116m8.467-2.116v2.116m8.467-2.116v2.116m8.466-2.116v2.116m8.467-2.116v2.116m8.467-2.116v2.116m8.466-2.116v2.116m8.467-2.116v2.116m8.467-2.116v2.116m8.466-2.116v2.116m8.467-2.116v2.116m8.467-2.116v2.116m8.466-2.116v2.116m8.467-2.116v2.116m8.467-2.116v2.116m8.466-2.116v2.116m-203.2-2.116v2.116M12.7 28.575v2.117m8.467-2.117v2.117m8.466-2.117v2.117m8.467-2.117v2.117m8.467-2.117v2.117m8.466-2.117v2.117m8.467-2.117v2.117m8.467-2.117v2.117m8.466-2.117v2.117m8.467-2.117v2.117m8.467-2.117v2.117m8.466-2.117v2.117m8.467-2.117v2.117m8.467-2.117v2.117m8.466-2.117v2.117m8.467-2.117v2.117m8.467-2.117v2.117m8.466-2.117v2.117m8.467-2.117v2.117m8.467-2.117v2.117m8.466-2.117v2.117m8.467-2.117v2.117m8.467-2.117v2.117m8.466-2.117v2.117m-203.2-2.117v2.117"
|
||||
id="path265" />
|
||||
<path
|
||||
stroke-width="0.397"
|
||||
stroke="#000000"
|
||||
fill="none"
|
||||
d="m 4.233,25.4 h 4.234 v -8.467 l 4.232395,4.74e-4 v 8.466737 h 4.233368 v -8.466737 h 4.233369 v 8.466737 h 4.233 l 3.68e-4,-8.466737 h 4.233368 v 8.466737 h 4.233369 v -8.466737 h 8.466737 v 8.466737 L 46.567,25.4 v 0 l -6.58e-4,2.11e-4 v -8.466737 h 4.233369 v 8.466737 h 4.233368 v -8.466737 h 4.233368 v 8.466737 h 4.233369 v -8.466737 l 4.233368,0 v 8.467 h 8.467 v -8.467 h 4.233 v 8.467 h 4.233 v -8.467 h 8.467 v 8.467 h 8.466996 v -8.467 h 8.466 v 8.467 h 4.234 v -8.467 h 4.233 v 8.467 h 4.233 v -8.467 h 4.234 v 8.467 h 4.233 v -8.467 h 4.233 v 8.467 h 4.234 v -8.467 h 4.233 v 8.467 h 8.467 v -8.467 h 4.233 v 0 h 4.233 v 8.467 h 4.234 v -8.467 h 4.233 v 8.467 h 4.233"
|
||||
id="path267"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
|
||||
<path
|
||||
fill="#ececec"
|
||||
d="m 173.56739,14.81687 33.86695,-8e-5 v 12.700105 l -33.86695,0 z"
|
||||
id="path7340"
|
||||
style="stroke-width:1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<text
|
||||
filter="url(#b)"
|
||||
font-family="sans-serif"
|
||||
font-size="10.667px"
|
||||
font-weight="400"
|
||||
style="line-height:1.25;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;filter:url(#b-1)"
|
||||
x="-0.70300001"
|
||||
y="7.9169998"
|
||||
transform="matrix(0.26458,0,0,0.26458,175.96136,18.086847)"
|
||||
id="text113-5"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-0.70300001"
|
||||
y="7.9169998"
|
||||
id="tspan11983">Additional words, if</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="-0.70300001"
|
||||
y="21.25075"
|
||||
id="tspan13576">any</tspan></text>
|
||||
<path
|
||||
d="m 173.56807,34.925309 2.11601,-3.175006 29.63358,-3.9e-5 2.11701,3.175006 -2.11701,3.175046 -29.63358,0 z"
|
||||
fill="none"
|
||||
stroke="#999999"
|
||||
stroke-width="0.265001"
|
||||
stroke-dasharray="0.793749, 0.264583"
|
||||
id="path16992"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 32 KiB |
@ -54,18 +54,29 @@ calculation includes the sync bit. Words are transmitted most significant bit
|
||||
|
||||

|
||||
|
||||
### 3299 Variant
|
||||
|
||||
The 3299 variant of the protocol includes a 6-bit address word at the start
|
||||
of each frame, specifying the multiplexer port the remainder of the frame
|
||||
should be sent to.
|
||||
|
||||

|
||||
|
||||
As with 10-bit words, the 6-bit address word starts with a sync bit and ends
|
||||
with an even parity bit.
|
||||
|
||||
### Words
|
||||
|
||||
All communication is initiated by the controller when it sends a frame
|
||||
containing a command word and optional data words. The attached device responds
|
||||
with a frame containing one or more data words.
|
||||
|
||||
### Words
|
||||
|
||||
Except for the `POLL` command response, words are either:
|
||||
|
||||
* Command - encapsulates a single 8-bit command byte, sent from a controller
|
||||
to an attached device
|
||||
* Data - encapsulates a single 8-bit data byte
|
||||
* Transmission Turnaround (TR/TA) - sent as an acknowledgment of a command
|
||||
* Transmission Turnaround (TT/AR) - sent as an acknowledgment of a command
|
||||
when there is no response data
|
||||
|
||||
| Bit | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
from .__about__ import __version__
|
||||
|
||||
from .interface import InterfaceFeature
|
||||
from .serial_interface import SerialInterface, open_serial_interface
|
||||
|
||||
from .protocol import (
|
||||
@ -48,6 +49,8 @@ from .features import (
|
||||
parse_features
|
||||
)
|
||||
|
||||
from .multiplexer import get_device_address
|
||||
|
||||
from .exceptions import (
|
||||
InterfaceError,
|
||||
ReceiveError,
|
||||
|
||||
@ -10,6 +10,9 @@ from .exceptions import ProtocolError
|
||||
class Interface:
|
||||
"""3270 coax interface."""
|
||||
|
||||
def __init__(self):
|
||||
self.features = set()
|
||||
|
||||
def reset(self):
|
||||
"""Reset the interface."""
|
||||
raise NotImplementedError
|
||||
@ -42,6 +45,11 @@ class Interface:
|
||||
def _transmit_receive(self, outbound_frames, response_lengths, timeout):
|
||||
raise NotImplementedError
|
||||
|
||||
class InterfaceFeature(Enum):
|
||||
"""Interface feature."""
|
||||
|
||||
PROTOCOL_3299 = 0x10
|
||||
|
||||
class FrameFormat(Enum):
|
||||
"""3270 coax frame format."""
|
||||
|
||||
|
||||
22
pycoax/coax/multiplexer.py
Normal file
22
pycoax/coax/multiplexer.py
Normal file
@ -0,0 +1,22 @@
|
||||
"""
|
||||
coax.multiplexer
|
||||
~~~~~~~~~~~~~~~~
|
||||
"""
|
||||
|
||||
PORT_MAP_3299 = [
|
||||
# The 3299-2 port numbers appear to be LSB first
|
||||
0b000000,
|
||||
0b100000,
|
||||
0b010000,
|
||||
0b110000,
|
||||
0b001000,
|
||||
0b101000,
|
||||
0b011000,
|
||||
0b111000
|
||||
]
|
||||
|
||||
def get_device_address(port):
|
||||
if port < 0 or port > 7:
|
||||
raise ValueError('Port must be between 0 and 7')
|
||||
|
||||
return PORT_MAP_3299[port]
|
||||
@ -11,7 +11,7 @@ from contextlib import contextmanager
|
||||
from serial import Serial
|
||||
from sliplib import SlipWrapper, ProtocolError
|
||||
|
||||
from .interface import Interface, FrameFormat
|
||||
from .interface import Interface, InterfaceFeature, FrameFormat
|
||||
from .protocol import pack_data_word
|
||||
from .exceptions import InterfaceError, InterfaceTimeout, ReceiveError, ReceiveTimeout
|
||||
|
||||
@ -22,6 +22,8 @@ class SerialInterface(Interface):
|
||||
if serial is None:
|
||||
raise ValueError('Serial port is required')
|
||||
|
||||
super().__init__()
|
||||
|
||||
self.serial = serial
|
||||
|
||||
self.slip_serial = SlipSerial(self.serial)
|
||||
@ -60,6 +62,13 @@ class SerialInterface(Interface):
|
||||
else:
|
||||
raise InterfaceError(f'Invalid reset response: {message}')
|
||||
|
||||
# Query features, if this is not a legacy firmware.
|
||||
if not self.legacy_firmware_detected:
|
||||
try:
|
||||
self.features = self._get_features()
|
||||
except InterfaceError:
|
||||
pass
|
||||
|
||||
def enter_dfu_mode(self):
|
||||
"""Enter device firmware upgrade mode."""
|
||||
message = bytes([0xf2])
|
||||
@ -71,18 +80,35 @@ class SerialInterface(Interface):
|
||||
if message[0] != 0x01:
|
||||
raise _convert_error(message)
|
||||
|
||||
def _transmit_receive(self, outbound_frames, response_lengths, timeout):
|
||||
if any(address is not None for (address, _) in outbound_frames):
|
||||
raise NotImplementedError('Interface does not support 3299 protocol')
|
||||
def _get_features(self):
|
||||
"""Get interface features."""
|
||||
message = bytes([0xf0, 0x07])
|
||||
|
||||
self._write_message(message)
|
||||
|
||||
message = self._read_message()
|
||||
|
||||
if message[0] != 0x01:
|
||||
return _convert_error(message)
|
||||
|
||||
known_feature_values = {feature.value for feature in InterfaceFeature}
|
||||
|
||||
features = {InterfaceFeature(value) for value in message[1:] if value in known_feature_values}
|
||||
|
||||
return features
|
||||
|
||||
def _transmit_receive(self, outbound_frames, response_lengths, timeout):
|
||||
if len(response_lengths) != len(outbound_frames):
|
||||
raise ValueError('Response lengths length must equal outbound frames length')
|
||||
|
||||
if any(address is not None for (address, _) in outbound_frames) and InterfaceFeature.PROTOCOL_3299 not in self.features:
|
||||
raise NotImplementedError('Interface does not support 3299 protocol')
|
||||
|
||||
# Pack all messages before sending.
|
||||
timeout_milliseconds = self._calculate_timeout_milliseconds(timeout)
|
||||
|
||||
messages = [_pack_transmit_receive_message(frame, response_length, timeout_milliseconds)
|
||||
for ((_, frame), response_length) in zip(outbound_frames, response_lengths)]
|
||||
messages = [_pack_transmit_receive_message(address, frame, response_length, timeout_milliseconds)
|
||||
for ((address, frame), response_length) in zip(outbound_frames, response_lengths)]
|
||||
|
||||
responses = []
|
||||
|
||||
@ -158,7 +184,7 @@ def open_serial_interface(serial_port, reset=True):
|
||||
|
||||
yield interface
|
||||
|
||||
def _pack_transmit_receive_message(frame, response_length, timeout_milliseconds):
|
||||
def _pack_transmit_receive_message(address, frame, response_length, timeout_milliseconds):
|
||||
message = bytes([0x06])
|
||||
|
||||
repeat_count = 0
|
||||
@ -197,6 +223,15 @@ def _pack_transmit_receive_message(frame, response_length, timeout_milliseconds)
|
||||
for byte in frame[1]:
|
||||
bytes_ += struct.pack('<H', pack_data_word(byte))
|
||||
|
||||
if address is not None:
|
||||
if address < 0 or address > 63:
|
||||
raise ValueError('Address must be between 0 and 63')
|
||||
|
||||
if repeat_count > 0:
|
||||
repeat_offset += 1
|
||||
|
||||
bytes_ = struct.pack('<H', 0x8000 | address) + bytes_
|
||||
|
||||
message += struct.pack('>H', (repeat_offset << 15) | repeat_count)
|
||||
message += bytes_
|
||||
message += struct.pack('>HH', response_length, timeout_milliseconds)
|
||||
|
||||
@ -5,7 +5,7 @@ import sliplib
|
||||
|
||||
import context
|
||||
|
||||
from coax.interface import FrameFormat
|
||||
from coax.interface import InterfaceFeature, FrameFormat
|
||||
from coax.serial_interface import SerialInterface
|
||||
from coax.exceptions import InterfaceError, ReceiveTimeout
|
||||
|
||||
@ -25,7 +25,7 @@ class SerialInterfaceResetTestCase(unittest.TestCase):
|
||||
self.interface.reset()
|
||||
|
||||
# Assert
|
||||
self.interface._write_message.assert_called_with(bytes.fromhex('01'))
|
||||
self.interface._write_message.assert_any_call(bytes.fromhex('01'))
|
||||
|
||||
def test_non_legacy_response_is_handled_correctly(self):
|
||||
# Act
|
||||
@ -191,9 +191,27 @@ class SerialInterfaceTransmitReceiveTestCase(unittest.TestCase):
|
||||
# Assert
|
||||
self.interface._write_message.assert_called_with(bytes.fromhex('06 00 00 ff 03 02 00 fe 03 00 01 01 f4'))
|
||||
|
||||
def test_addressed_frame(self):
|
||||
def test_addressed_frame_with_3299_protocol_feature(self):
|
||||
# Arrange
|
||||
self.interface.features.add(InterfaceFeature.PROTOCOL_3299)
|
||||
|
||||
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
|
||||
|
||||
# Act
|
||||
responses = self.interface._transmit_receive([(0b111000, (FrameFormat.WORDS, [0b1111111111, 0b0000000000]))], [1], None)
|
||||
|
||||
# Assert
|
||||
self.assertEqual(responses, [[0]])
|
||||
|
||||
self.interface._write_message.assert_called_with(bytes.fromhex('06 00 00 38 80 ff 03 00 00 00 01 00 00'))
|
||||
|
||||
def test_addressed_frame_with_no_3299_protocol_feature(self):
|
||||
# Arrange
|
||||
self.interface._read_message.return_value=bytes.fromhex('01 00 00')
|
||||
|
||||
# Act and assert
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self.interface._transmit_receive([(0b111000, (FrameFormat.WORD_DATA, 0b1111111111, [0x00, 0xff]))], [1], 0.5)
|
||||
self.interface._transmit_receive([(0b111000, (FrameFormat.WORDS, [0b1111111111, 0b0000000000]))], [1], None)
|
||||
|
||||
def test_multiple_frames(self):
|
||||
# Arrange
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user