Initial commit

This commit is contained in:
Andrew Kay
2019-06-26 22:36:14 -05:00
commit 37813a2727
39 changed files with 16406 additions and 0 deletions

13
LICENSE Normal file
View File

@@ -0,0 +1,13 @@
Copyright (c) 2019, Andrew Kay
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

14
README.md Normal file
View File

@@ -0,0 +1,14 @@
# coax-interface
> Hello mainframe!
coax-interface is a set of tools for interfacing with [IBM 3270](https://en.wikipedia.org/wiki/IBM_3270) type terminals.
## Contents
* [pycoax](pycoax) - Python IBM 3270 coaxial interface library
* [interface1](interface1) - A serial attached Arduino interface using the National Semiconductor DP8340 and DP8341
## See Also
* [oec](https://github.com/lowobservable/oec) - An open replacement for the IBM 3174 Establishment Controller

32
interface1/README.md Normal file
View File

@@ -0,0 +1,32 @@
# interface1
A serial attached Arduino interface using the National Semiconductor DP8340 and DP8341.
## Schematic
![Schematic](hardware/schematic.svg)
## Materials
This interface requires an [Arduino Mega](https://store.arduino.cc/usa/mega-2560-r3).
Item | Quantity | Description | Reference | Part Number | Source
:----:|---------:|-------------------------------|-----------|-------------------------------|----------------
1 | 1 | IBM 3270 Protocol Transmitter | U1 | National Semiconductor DP8340 | eBay - Obsolete
2 | 1 | IBM 3270 Protocol Receiver | U2 | National Semiconductor DP8341 | eBay - Obsolete
3 | 1 | Quad RS-422 Line Driver | U3 | Texas Instruments DS3487 | eBay - Obsolete
4 | 1 | Pulse Transformer - 1:1:1 | T1 | Pulse PE-5762 | eBay - Obsolete
5 | 1 | Crystal - 18.867 MHz | Y1 | IQD LFXTAL057125 * | [Mouser](https://www.mouser.com/ProductDetail/IQD/LFXTAL057125Bulk?qs=%2Fha2pyFaduieSzBxw7UAJRZlCXjBZuIKPyofrMyYW7wVunrhuBMeiQd4MCF50LLz)
6 | 2 | Resistor - 33 ohm | R2, R4 | | [Mouser](https://www.mouser.com/ProductDetail/Xicon/271-33-RC?qs=sGAEpiMZZMu61qfTUdNhGzoeXLT9qgk%252BV159XfY8c4Q%3D)
7 | 1 | Resistor - 120 ohm | R6 | | [Mouser](https://www.mouser.com/ProductDetail/Xicon/271-120-RC?qs=sGAEpiMZZMu61qfTUdNhG7Of23Pr6gu8rRE5UXBJoDw%3D)
8 | 2 | Resistor - 150 ohm | R1, R5 | | [Mouser](https://www.mouser.com/ProductDetail/Xicon/271-150-RC?qs=sGAEpiMZZMu61qfTUdNhG2ZzrN2CiS9nBcPQNrtAXYk%3D)
9 | 1 | Resistor - 500 ohm | R7 | | [Mouser](https://www.mouser.com/ProductDetail/Xicon/271-499-RC?qs=sGAEpiMZZMu61qfTUdNhG6lpw21m8SOsvE2iEnaSg1s%3D)
10 | 1 | Resistor - 510 ohm | R3 | | [Mouser](https://www.mouser.com/ProductDetail/Xicon/271-510-RC?qs=sGAEpiMZZMu61qfTUdNhG9RrhBeDi8B8FBVTnOgGHiw%3D)
11 | 1 | Capacitor - 30pF | C1 | | [Mouser](https://www.mouser.com/ProductDetail/Vishay-Cera-Mite/561R10TCCQ30?qs=sGAEpiMZZMt1mVBmZSXTPNbSVgF1iSv4q4pBhPBLwuM%3D)
12 | 1 | Coax Connector | J1 | |
\* - SMD
## Firmware
The firmware currently provides the ability to send commands and receive responses - it is designed to be used to implement a terminal controller, not to emulate a terminal.

View File

@@ -0,0 +1,305 @@
// Copyright (c) 2019, Andrew Kay
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <Arduino.h>
#include "CoaxTransceiver.h"
// Arduino Mega pins...
//
// Arduino Arduino Port Label DP8340N DP8341N
// Pin and Mask Pin Pin
// ---------|--------------|-----------------|---------|---------
// 36 | PC1 | D2 | 10 | 14
// 37 | PC0 | D3 | 9 | 15
// 29 | PA7 | D4 | 8 | 16
// 28 | PA6 | D5 | 7 | 17
// 27 | PA5 | D6 | 6 | 18
// 26 | PA4 | D7 | 5 | 19
// 25 | PA3 | D8 | 4 | 20
// 24 | PA2 | D9 | 3 | 21
// 23 | PA1 | D10 | 2 | 22
// 22 | PA0 | D11 | 1 | 23
// --------- -------------- ----------------- --------- ---------
// 8 | PH5 0x20 | REGISTER LOAD | 23 |
// 9 | PH6 0x40 | REGISTERS FULL | 22 |
// 10 | | AUTO RESPONSE | 21 |
// 11 | | EVEN/ODD PARITY | 18 |
// 12 | PB6 0x40 | PARITY CONTROL | 19 |
// --------- -------------- ----------------- --------- ---------
// 18* | PD3 0x08 | RECEIVER ACTIVE | | 7
// 2 | PE4 0x10 | DATA AVAILABLE | | 10
// 3 | PE5 0x20 | ERROR | | 8
// 4 | | DATA CONTROL | | 5
// 5 | PE3 0x08 | REGISTER READ | | 9
// 6 | PH3 0x08 | OUTPUT CONTROL | | 11
// 7 | PH4 0x10 | OUTPUT ENABLE | | 13
//
// * - Interrupt capable pin
#define TX_REGISTER_LOAD_PIN 8
#define TX_REGISTERS_FULL_PIN 9
#define TX_AUTO_RESPONSE_PIN 10
#define TX_EVEN_ODD_PARITY_PIN 11
#define TX_PARITY_CONTROL_PIN 12
#define RX_ACTIVE_PIN 18
#define RX_DATA_AVAILABLE_PIN 2
#define RX_ERROR_PIN 3
#define RX_DATA_CONTROL_PIN 4
#define RX_REGISTER_READ_PIN 5
#define RX_OUTPUT_CONTROL_PIN 6
#define RX_OUTPUT_ENABLE_PIN 7
#define RX_STATE_DISABLED 0
#define RX_STATE_WAITING 1
#define RX_STATE_RECEIVING 2
#define RX_STATE_RECEIVED 3
static volatile uint8_t CoaxTransceiver::rxState;
static volatile uint16_t *CoaxTransceiver::rxBuffer;
static volatile size_t CoaxTransceiver::rxBufferSize;
static volatile int /* ssize_t */ CoaxTransceiver::rxBufferCount;
#define NOP __asm__("nop\n\t")
static void CoaxTransceiver::setup() {
// Configure data bus.
dataBusSetup();
// Configure receiver (DP8341N).
rxSetup();
// Configure transmitter (DP8340N).
txSetup();
}
static int /* ssize_t */ CoaxTransceiver::transmitReceive(uint16_t commandWord, uint8_t *dataBuffer, size_t dataBufferCount, uint16_t *receiveBuffer, size_t receiveBufferSize, uint16_t timeout) {
int returnValue = transmit(commandWord, dataBuffer, dataBufferCount);
if (returnValue < 0) {
return returnValue;
}
return receive(receiveBuffer, receiveBufferSize, timeout);
}
static void CoaxTransceiver::dataBusSetup() {
DDRA = B00000000;
DDRC = B00000000;
}
static void CoaxTransceiver::rxSetup() {
// Data Control - Amplifier Inputs
pinMode(RX_DATA_CONTROL_PIN, OUTPUT);
digitalWrite(RX_DATA_CONTROL_PIN, HIGH);
// Register Read
pinMode(RX_REGISTER_READ_PIN, OUTPUT);
digitalWrite(RX_REGISTER_READ_PIN, HIGH);
// Output Control - Data
pinMode(RX_OUTPUT_CONTROL_PIN, OUTPUT);
digitalWrite(RX_OUTPUT_CONTROL_PIN, HIGH);
// Output Enable - Active
pinMode(RX_OUTPUT_ENABLE_PIN, OUTPUT);
digitalWrite(RX_OUTPUT_ENABLE_PIN, HIGH);
// Receiver Active
pinMode(RX_ACTIVE_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(RX_ACTIVE_PIN), rxActiveInterrupt, RISING);
// Data Available
pinMode(RX_DATA_AVAILABLE_PIN, INPUT);
// Error
pinMode(RX_ERROR_PIN, INPUT);
}
static void CoaxTransceiver::txSetup() {
// Register Load
pinMode(TX_REGISTER_LOAD_PIN, OUTPUT);
digitalWrite(TX_REGISTER_LOAD_PIN, HIGH);
// Auto Response - Data
pinMode(TX_AUTO_RESPONSE_PIN, OUTPUT);
digitalWrite(TX_AUTO_RESPONSE_PIN, HIGH);
// Even/Odd Parity - Even
pinMode(TX_EVEN_ODD_PARITY_PIN, OUTPUT);
digitalWrite(TX_EVEN_ODD_PARITY_PIN, HIGH);
// Parity Control - Data
pinMode(TX_PARITY_CONTROL_PIN, OUTPUT);
digitalWrite(TX_PARITY_CONTROL_PIN, HIGH);
// Registers Full
pinMode(TX_REGISTERS_FULL_PIN, INPUT);
}
static int /* ssize_t */ CoaxTransceiver::transmit(uint16_t commandWord, uint8_t *dataBuffer, size_t dataCount) {
// Ensure receiver is inactive.
if (rxState != RX_STATE_DISABLED) {
return ERROR_TX_RECEIVER_ACTIVE;
}
if ((PIND & 0x8) == 0x8) {
return ERROR_TX_RECEIVER_ACTIVE;
}
// Disable interrupts.
noInterrupts();
// Disable receiver output.
PORTH &= ~0x10; // RX Output Enable - Low (Disable)
// Configure data bus for output.
DDRA = B11111111;
DDRC = B00000011;
// Send command word - we make an assumption here that TX_REGISTERS_FULL is not set.
PORTC = (PINC & 0xfc) | ((commandWord >> 8) & 0x3);
PORTA = commandWord & 0xff;
PORTH &= ~0x20; // TX Register Load - Low (Load)
PORTH |= 0x20; // TX Register Load - High
// Send data - offload parity computation to DP8340.
if (dataCount > 0) {
// Enable transmitter parity calculation.
PORTB &= ~0x40; // TX Parity Control - Low
for (int index = 0; index < dataCount; index++) {
// Wait while TX Registers Full is high.
while ((PINH & 0x40) == 0x40) {
NOP;
}
uint8_t data = dataBuffer[index];
PORTC = (PINC & 0xfc) | ((data >> 6) & 0x3);
PORTA = (data << 2);
PORTH &= ~0x20; // TX Register Load - Low (Load)
PORTH |= 0x20; // TX Register Load - High
}
// Disable transmitter parity calculation.
PORTB |= 0x40; // TX Parity Control - High
}
// Configure data bus for input.
DDRA = B00000000;
DDRC = B00000000;
// Enable receiver output.
PORTH |= 0x10; // RX Output Enable - High (Enable)
// Enable interrupts.
interrupts();
return dataCount;
}
static int /* ssize_t */ CoaxTransceiver::receive(uint16_t *buffer, size_t bufferSize, uint16_t timeout) {
rxBuffer = buffer;
rxBufferSize = bufferSize;
rxState = RX_STATE_WAITING;
if (timeout > 0) {
unsigned long startTime = millis();
while (rxState == RX_STATE_WAITING) {
// https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html#unsigned
if ((millis() - startTime) > timeout) {
rxState = RX_STATE_DISABLED;
return ERROR_RX_TIMEOUT;
}
}
}
while (rxState != RX_STATE_RECEIVED) {
NOP;
}
rxState = RX_STATE_DISABLED;
return rxBufferCount;
}
static void CoaxTransceiver::rxActiveInterrupt() {
uint16_t data;
uint8_t mask;
if (rxState == RX_STATE_DISABLED) {
return;
}
rxState = RX_STATE_RECEIVING;
rxBufferCount = 0;
do {
while ((PINE & 0x30) == 0) {
NOP;
}
if (/* ERROR */ (PINE & 0x20) == 0x20) {
mask = 0x20;
PORTH &= ~0x8; // Output Control - Low (Error)
PORTE &= ~0x8; // Register Read - Low
// Read and mark as error.
data = (((PINC & 0x3) | 0x80) << 8) | PINA;
PORTE |= 0x8; // Register Read - High
PORTH |= 0x8; // Output Control - High (Data)
} else if (/* DATA AVAILABLE */ (PINE & 0x10) == 0x10) {
mask = 0x10;
PORTE &= ~0x8; // Register Read - Low
// Read.
data = ((PINC & 0x3) << 8) | PINA;
PORTE |= 0x8; // Register Read - High
}
if (rxBufferCount >= rxBufferSize) {
rxBufferCount = ERROR_RX_OVERFLOW;
goto EXIT;
}
rxBuffer[rxBufferCount++] = data;
while ((PINE & mask) == mask) {
NOP;
}
} while ((PIND & 0x8) == 0x8);
EXIT:
rxState = RX_STATE_RECEIVED;
}

View File

@@ -0,0 +1,40 @@
// Copyright (c) 2019, Andrew Kay
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#pragma once
#include <Arduino.h>
#define ERROR_TX_RECEIVER_ACTIVE -1
#define ERROR_RX_TIMEOUT -2
#define ERROR_RX_OVERFLOW -3
class CoaxTransceiver {
public:
static void setup();
static int /* ssize_t */ transmitReceive(uint16_t commandWord, uint8_t *dataBuffer, size_t dataBufferCount, uint16_t *receiveBuffer, size_t receiveBufferSize, uint16_t timeout);
private:
static void dataBusSetup();
static void rxSetup();
static void txSetup();
static int /* ssize_t */ transmit(uint16_t commandWord, uint8_t *dataBuffer, size_t dataCount);
static int /* ssize_t */ receive(uint16_t *buffer, size_t bufferSize, uint16_t timeout);
static void rxActiveInterrupt();
static volatile uint8_t rxState;
static volatile uint16_t *rxBuffer;
static volatile size_t rxBufferSize;
static volatile int /* ssize_t */ rxBufferCount;
};

View File

@@ -0,0 +1,304 @@
// Copyright (c) 2019, Andrew Kay
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <Arduino.h>
#include "CoaxTransceiver.h"
#define COMMAND_RESET 0x01
#define COMMAND_EXECUTE 0x02
#define COMMAND_EXECUTE_OFFLOAD 0x03
#define ERROR_INVALID_MESSAGE 1
#define ERROR_UNKNOWN_COMMAND 2
#define ERROR_UNKNOWN_OFFLOAD_COMMAND 3
#define UNPACK_DATA_WORD(w) (uint8_t) ((w >> 2) & 0xff)
void handleResetCommand(uint8_t *buffer, int bufferCount) {
uint8_t response[] = { 0x01, 0x00, 0x00, 0x01 };
sendMessage(response, 4);
}
void handleExecuteCommand(uint8_t *buffer, int bufferCount) {
if (bufferCount < 6) {
sendErrorMessage(ERROR_INVALID_MESSAGE);
return;
}
uint16_t commandWord = (buffer[0] << 8) | buffer[1];
uint16_t receiveCount = (buffer[2] << 8) | buffer[3];
uint16_t timeout = (buffer[4] << 8) | buffer[5];
uint8_t *dataBuffer = buffer + 6;
uint16_t dataBufferCount = bufferCount - 6;
uint16_t *receiveBuffer = (uint16_t *) (buffer + 2);
bufferCount = CoaxTransceiver::transmitReceive(commandWord, dataBuffer, dataBufferCount, receiveBuffer, receiveCount, timeout);
if (bufferCount < 0) {
sendErrorMessage(100 + ((-1) * bufferCount));
return;
}
// Send the response message.
buffer[1] = 0x01;
bufferCount = 1 + (bufferCount * 2);
sendMessage(buffer + 1, bufferCount);
}
void handleExecuteOffloadCommand(uint8_t *buffer, int bufferCount) {
if (bufferCount < 1) {
sendErrorMessage(ERROR_INVALID_MESSAGE);
return;
}
uint8_t command = buffer[0];
if (command == 0x01) {
handleOffloadLoadAddressCounter(buffer + 1, bufferCount - 1);
} else if (command == 0x02) {
handleOffloadWrite(buffer + 1, bufferCount - 1);
} else {
sendErrorMessage(ERROR_UNKNOWN_OFFLOAD_COMMAND);
}
}
void handleOffloadLoadAddressCounter(uint8_t *buffer, int bufferCount) {
uint16_t response;
if (bufferCount < 2) {
sendErrorMessage(ERROR_INVALID_MESSAGE);
return;
}
uint8_t hi = buffer[0];
uint8_t lo = buffer[1];
// TODO: error handling...
CoaxTransceiver::transmitReceive(/* LOAD_ADDRESS_COUNTER_HI */ 0x11, &hi, 1, &response, 1, 0);
CoaxTransceiver::transmitReceive(/* LOAD_ADDRESS_COUNTER_LO */ 0x51, &lo, 1, &response, 1, 0);
// Send the response message.
uint8_t message[] = { 0x01 };
sendMessage(message, 1);
}
void handleOffloadWrite(uint8_t *buffer, int bufferCount) {
uint16_t response;
if (bufferCount < 5) {
sendErrorMessage(ERROR_INVALID_MESSAGE);
return;
}
uint8_t addressHi = buffer[0];
uint8_t addressLo = buffer[1];
bool restoreOriginalAddress = buffer[2];
uint16_t repeatCount = (buffer[3] << 8) | buffer[4];
uint8_t *dataBuffer = buffer + 5;
uint16_t dataBufferCount = bufferCount - 5;
if (dataBufferCount < 1) {
sendErrorMessage(ERROR_INVALID_MESSAGE);
return;
}
// Repeat the provided data if applicable.
if (repeatCount > 0) {
uint16_t dataBufferIndex = dataBufferCount;
for (int repeatIndex = 0; repeatIndex < repeatCount; repeatIndex++) {
for (int index = 0; index < dataBufferCount; index++) {
dataBuffer[dataBufferIndex++] = dataBuffer[index];
}
}
dataBufferCount *= (repeatCount + 1);
}
// Store original address if applicable.
uint8_t originalAddressHi;
uint8_t originalAddressLo;
if (restoreOriginalAddress) {
CoaxTransceiver::transmitReceive(/* READ_ADDRESS_COUNTER_HI */ 0x15, NULL, 0, &response, 1, 0);
originalAddressHi = UNPACK_DATA_WORD(response);
CoaxTransceiver::transmitReceive(/* READ_ADDRESS_COUNTER_LO */ 0x55, NULL, 0, &response, 1, 0);
originalAddressLo = UNPACK_DATA_WORD(response);
}
// Move to start address if applicable.
if (!(addressHi == 0xff && addressLo == 0xff)) {
CoaxTransceiver::transmitReceive(/* LOAD_ADDRESS_COUNTER_HI */ 0x11, &addressHi, 1, &response, 1, 0);
CoaxTransceiver::transmitReceive(/* LOAD_ADDRESS_COUNTER_LO */ 0x51, &addressLo, 1, &response, 1, 0);
}
// Write buffer.
CoaxTransceiver::transmitReceive(/* WRITE_DATA */ 0x31, dataBuffer, dataBufferCount, &response, 1, 0);
// Restore original address if applicable.
if (restoreOriginalAddress) {
CoaxTransceiver::transmitReceive(/* LOAD_ADDRESS_COUNTER_HI */ 0x11, &originalAddressHi, 1, &response, 1, 0);
CoaxTransceiver::transmitReceive(/* LOAD_ADDRESS_COUNTER_LO */ 0x51, &originalAddressLo, 1, &response, 1, 0);
}
// Send the response message.
uint8_t message[] = { 0x01 };
sendMessage(message, 1);
}
void handleMessage(uint8_t *buffer, int bufferCount) {
if (bufferCount < 1) {
sendErrorMessage(ERROR_INVALID_MESSAGE);
return;
}
uint8_t command = buffer[0];
if (command == COMMAND_RESET) {
handleResetCommand(buffer + 1, bufferCount - 1);
} else if (command == COMMAND_EXECUTE) {
handleExecuteCommand(buffer + 1, bufferCount - 1);
} else if (command == COMMAND_EXECUTE_OFFLOAD) {
handleExecuteOffloadCommand(buffer + 1, bufferCount - 1);
} else {
sendErrorMessage(ERROR_UNKNOWN_COMMAND);
}
}
#define FRAME_END 0xc0
#define FRAME_ESCAPE 0xdb
#define FRAME_ESCAPE_END 0xdc
#define FRAME_ESCAPE_ESCAPE 0xdd
enum {
WAIT_START,
DATA,
ESCAPE
} frameState;
#define FRAME_BUFFER_SIZE (25 * 80) + 32
uint8_t frameBuffer[FRAME_BUFFER_SIZE];
int frameBufferCount = 0;
void handleFrame(uint8_t *buffer, int bufferCount) {
if (bufferCount < 4) {
sendErrorMessage(ERROR_INVALID_MESSAGE);
return;
}
int count = (buffer[0] << 8) | buffer[1];
if (bufferCount - 4 != count) {
sendErrorMessage(ERROR_INVALID_MESSAGE);
return;
}
handleMessage(buffer + 2, count);
}
void sendMessage(uint8_t *buffer, int bufferCount) {
Serial.write((char) FRAME_END);
// Write the length.
Serial.write((char) bufferCount >> 8);
Serial.write((char) bufferCount);
for (int index = 0; index < bufferCount; index++) {
if (buffer[index] == FRAME_END) {
Serial.write((char) FRAME_ESCAPE);
Serial.write((char) FRAME_ESCAPE_END);
} else if (buffer[index] == FRAME_ESCAPE) {
Serial.write((char) FRAME_ESCAPE);
Serial.write((char) FRAME_ESCAPE_ESCAPE);
} else {
Serial.write((char) buffer[index]);
}
}
// Write the placeholder for checksum.
Serial.write((char) 0x00);
Serial.write((char) 0x00);
Serial.write((char) FRAME_END);
Serial.flush();
}
void sendErrorMessage(uint8_t code) {
uint8_t message[] = { 0x02, code };
sendMessage(message, 2);
}
void setup() {
// Configure serial port and state machine.
Serial.begin(115200);
frameState = WAIT_START;
while (Serial.available() > 0) {
Serial.read();
}
// Configure the transceiver.
CoaxTransceiver::setup();
}
void loop() {
if (Serial.available() > 0) {
uint8_t byte = Serial.read();
if (frameState == WAIT_START) {
if (byte == FRAME_END) {
frameState = DATA;
}
} else if (frameState == DATA) {
if (byte == FRAME_END) {
if (frameBufferCount > 0) {
handleFrame(frameBuffer, frameBufferCount);
}
frameBufferCount = 0;
} else if (byte == FRAME_ESCAPE) {
frameState = ESCAPE;
} else {
// TODO: overflow...
frameBuffer[frameBufferCount++] = byte;
}
} else if (frameState == ESCAPE) {
if (byte == FRAME_ESCAPE_END) {
// TODO: overflow...
frameBuffer[frameBufferCount++] = FRAME_END;
} else if (byte == FRAME_ESCAPE_ESCAPE) {
// TODO: overflow...
frameBuffer[frameBufferCount++] = FRAME_ESCAPE;
}
frameState = DATA;
}
}
}

View File

@@ -0,0 +1,256 @@
EESchema-LIBRARY Version 2.4
#encoding utf-8
#
# Connector_Conn_Coaxial
#
DEF Connector_Conn_Coaxial J 0 40 Y N 1 F N
F0 "J" 10 120 50 H V C CNN
F1 "Connector_Conn_Coaxial" 115 0 50 V V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
*BNC*
*SMA*
*SMB*
*SMC*
*Cinch*
$ENDFPLIST
DRAW
A -2 0 71 1636 0 0 1 10 N -70 20 70 0
A -1 0 71 0 -1638 0 1 10 N 70 0 -70 -20
C 0 0 20 0 1 8 N
P 2 0 1 0 -100 0 -20 0 N
P 2 0 1 0 0 -100 0 -70 N
X In 1 -200 0 100 R 50 50 1 1 P
X Ext 2 0 -200 100 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Device_C
#
DEF Device_C C 0 10 N Y 1 F N
F0 "C" 25 100 50 H V L CNN
F1 "Device_C" 25 -100 50 H V L CNN
F2 "" 38 -150 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
C_*
$ENDFPLIST
DRAW
P 2 0 1 20 -80 -30 80 -30 N
P 2 0 1 20 -80 30 80 30 N
X ~ 1 0 150 110 D 50 50 1 1 P
X ~ 2 0 -150 110 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Device_Crystal
#
DEF Device_Crystal Y 0 40 N N 1 F N
F0 "Y" 0 150 50 H V C CNN
F1 "Device_Crystal" 0 -150 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Crystal*
$ENDFPLIST
DRAW
S -45 100 45 -100 0 1 12 N
P 2 0 1 0 -100 0 -75 0 N
P 2 0 1 20 -75 -50 -75 50 N
P 2 0 1 20 75 -50 75 50 N
P 2 0 1 0 100 0 75 0 N
X 1 1 -150 0 50 R 50 50 1 1 P
X 2 2 150 0 50 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Device_R_US
#
DEF Device_R_US R 0 0 N Y 1 F N
F0 "R" 100 0 50 V V C CNN
F1 "Device_R_US" -100 0 50 V V C CNN
F2 "" 40 -10 50 V I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
R_*
$ENDFPLIST
DRAW
P 2 0 1 0 0 -90 0 -100 N
P 2 0 1 0 0 90 0 100 N
P 5 0 1 0 0 -30 40 -45 0 -60 -40 -75 0 -90 N
P 5 0 1 0 0 30 40 15 0 0 -40 -15 0 -30 N
P 5 0 1 0 0 90 40 75 0 60 -40 45 0 30 N
X ~ 1 0 150 50 D 50 50 1 1 P
X ~ 2 0 -150 50 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# library_DP8340
#
DEF library_DP8340 U 0 40 Y Y 1 F N
F0 "U" 0 -100 50 H V C CNN
F1 "library_DP8340" 0 100 50 H V C CNN
F2 "MODULE" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
S -450 -750 450 750 1 0 0 N
X DI11 1 -750 550 300 R 50 50 1 1 U
X DI2 10 -750 -350 300 R 50 50 1 1 U
X CLK_OUT 11 -750 -450 300 R 50 50 1 1 U
X GND 12 -750 -550 300 R 50 50 1 1 U
X X1 13 750 -550 300 L 50 50 1 1 U
X X2 14 750 -450 300 L 50 50 1 1 U
X DATA_DLY 15 750 -350 300 L 50 50 1 1 U
X DATA_OUT1 16 750 -250 300 L 50 50 1 1 U
X DATA_OUT2 17 750 -150 300 L 50 50 1 1 U
X EVEN_ODD 18 750 -50 300 L 50 50 1 1 U
X PARITY_CTL 19 750 50 300 L 50 50 1 1 U
X DI10 2 -750 450 300 R 50 50 1 1 U
X TX_ACTIVE 20 750 150 300 L 50 50 1 1 U
X AUTO_RESP 21 750 250 300 L 50 50 1 1 U
X REG_FULL 22 750 350 300 L 50 50 1 1 U
X REG_LOAD 23 750 450 300 L 50 50 1 1 U
X VCC 24 750 550 300 L 50 50 1 1 U
X DI9 3 -750 350 300 R 50 50 1 1 U
X DI8 4 -750 250 300 R 50 50 1 1 U
X DI7 5 -750 150 300 R 50 50 1 1 U
X DI6 6 -750 50 300 R 50 50 1 1 U
X DI5 7 -750 -50 300 R 50 50 1 1 U
X DI4 8 -750 -150 300 R 50 50 1 1 U
X DI3 9 -750 -250 300 R 50 50 1 1 U
ENDDRAW
ENDDEF
#
# library_DP8341
#
DEF library_DP8341 U 0 40 Y Y 1 F N
F0 "U" 0 -100 50 H V C CNN
F1 "library_DP8341" 0 100 50 H V C CNN
F2 "MODULE" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
S -450 -750 450 750 1 0 0 N
X RX_DISABLE 1 -750 550 300 R 50 50 1 1 U
X DATA_AVAIL 10 -750 -350 300 R 50 50 1 1 U
X OUTPUT_CTL 11 -750 -450 300 R 50 50 1 1 U
X GND 12 -750 -550 300 R 50 50 1 1 U
X OUTPUT_EN 13 750 -550 300 L 50 50 1 1 U
X DO2 14 750 -450 300 L 50 50 1 1 U
X DO3 15 750 -350 300 L 50 50 1 1 U
X DO4 16 750 -250 300 L 50 50 1 1 U
X DO5 17 750 -150 300 L 50 50 1 1 U
X DO6 18 750 -50 300 L 50 50 1 1 U
X DO7 19 750 50 300 L 50 50 1 1 U
X +AMP_IN 2 -750 450 300 R 50 50 1 1 U
X DO8 20 750 150 300 L 50 50 1 1 U
X DO9 21 750 250 300 L 50 50 1 1 U
X DO10 22 750 350 300 L 50 50 1 1 U
X DO11 23 750 450 300 L 50 50 1 1 U
X VCC 24 750 550 300 L 50 50 1 1 U
X -AMP_IN 3 -750 350 300 R 50 50 1 1 U
X DATA 4 -750 250 300 R 50 50 1 1 U
X DATA_CTL 5 -750 150 300 R 50 50 1 1 U
X CLOCK 6 -750 50 300 R 50 50 1 1 U
X RX_ACTIVE 7 -750 -50 300 R 50 50 1 1 U
X ERROR 8 -750 -150 300 R 50 50 1 1 U
X REG_READ 9 -750 -250 300 R 50 50 1 1 U
ENDDRAW
ENDDEF
#
# library_DS3487
#
DEF library_DS3487 U 0 40 Y Y 1 F N
F0 "U" 0 -100 50 H V C CNN
F1 "library_DS3487" 0 100 50 H V C CNN
F2 "MODULE" 0 0 50 H I C CNN
F3 "DOCUMENTATION" 0 0 50 H I C CNN
DRAW
S -450 -550 450 550 1 0 0 N
X PIN1 1 -750 350 300 R 50 50 1 1 U
X PIN10 10 750 -250 300 L 50 50 1 1 U
X PIN11 11 750 -150 300 L 50 50 1 1 U
X PIN12 12 750 -50 300 L 50 50 1 1 U
X PIN13 13 750 50 300 L 50 50 1 1 U
X PIN14 14 750 150 300 L 50 50 1 1 U
X PIN15 15 750 250 300 L 50 50 1 1 U
X PIN16 16 750 350 300 L 50 50 1 1 U
X PIN2 2 -750 250 300 R 50 50 1 1 U
X PIN3 3 -750 150 300 R 50 50 1 1 U
X PIN4 4 -750 50 300 R 50 50 1 1 U
X PIN5 5 -750 -50 300 R 50 50 1 1 U
X PIN6 6 -750 -150 300 R 50 50 1 1 U
X PIN7 7 -750 -250 300 R 50 50 1 1 U
X PIN8 8 -750 -350 300 R 50 50 1 1 U
X PIN9 9 750 -350 300 L 50 50 1 1 U
ENDDRAW
ENDDEF
#
# library_xxxx
#
DEF library_xxxx T 0 20 Y N 1 F N
F0 "T" 0 550 50 H V C CNN
F1 "library_xxxx" 0 -550 50 H V C CNN
F2 "Transformer_SMD:Pulse_PA2002NL-PA2008NL-PA2009NL" 0 0 50 H I C CNN
F3 "" -300 0 50 H I C CNN
DRAW
A -100 -90 30 900 -900 0 1 8 N -100 -60 -100 -120
A -100 -30 30 900 -900 0 1 8 N -100 0 -100 -60
A -100 30 30 900 -900 0 1 8 N -100 60 -100 0
A 100 -390 30 -900 900 0 1 8 N 100 -420 100 -360
A 100 -330 30 -900 900 0 1 8 N 100 -360 100 -300
A 100 -270 30 -900 900 0 1 8 N 100 -300 100 -240
A 100 -210 30 -900 900 0 1 8 N 100 -240 100 -180
A 100 210 30 -900 900 0 1 8 N 100 180 100 240
A 100 270 30 -900 900 0 1 8 N 100 240 100 300
A 100 330 30 -900 900 0 1 8 N 100 300 100 360
A 100 390 30 -900 900 0 1 8 N 100 360 100 420
A -100 90 30 900 -900 1 1 8 N -100 120 -100 60
C -100 90 10 0 1 0 F
C 100 -210 10 0 1 0 F
C 100 390 10 0 1 0 F
P 2 0 1 0 -100 -120 -100 -200 N
P 2 0 1 0 -100 200 -100 120 N
P 2 0 1 0 -25 425 -25 -425 N
P 2 0 1 0 25 425 25 -425 N
P 2 0 1 0 100 -420 100 -500 N
P 2 0 1 0 100 -100 100 -180 N
P 2 0 1 0 100 180 100 100 N
P 2 0 1 0 100 500 100 420 N
X ~ 1 200 500 100 L 50 50 1 1 P
X ~ 2 200 100 100 L 50 50 1 1 P
X ~ 3 -200 200 100 R 50 50 1 1 P
X ~ 4 -200 -200 100 R 50 50 1 1 P
X ~ 5 200 -100 100 L 50 50 1 1 P
X ~ 6 200 -500 100 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# power_GND
#
DEF power_GND #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -250 50 H I C CNN
F1 "power_GND" 0 -150 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
X GND 1 0 0 0 D 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# power_VCC
#
DEF power_VCC #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -150 50 H I C CNN
F1 "power_VCC" 0 150 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
C 0 75 25 0 1 0 N
P 2 0 1 0 0 0 0 50 N
X VCC 1 0 0 0 U 50 50 1 1 W N
ENDDRAW
ENDDEF
#
#End Library

View File

@@ -0,0 +1,3 @@
EESchema-DOCLIB Version 2.0
#
#End Doc Library

View File

@@ -0,0 +1,557 @@
EESchema Schematic File Version 4
EELAYER 29 0
EELAYER END
$Descr USLetter 11000 8500
encoding utf-8
Sheet 1 1
Title ""
Date ""
Rev ""
Comp ""
Comment1 ""
Comment2 ""
Comment3 ""
Comment4 "Based on the typical application from the DP8340 and DP8341 data sheets"
$EndDescr
$Comp
L library:DP8340 U1
U 1 1 5CFF4259
P 4200 2500
F 0 "U1" H 4200 3415 50 0000 C CNN
F 1 "DP8340" H 4200 3324 50 0000 C CNN
F 2 "MODULE" H 4200 2500 50 0001 C CNN
F 3 "" H 4200 2500 50 0001 C CNN
1 4200 2500
1 0 0 -1
$EndComp
$Comp
L Device:R_US R7
U 1 1 5D005C33
P 5450 3200
F 0 "R7" H 5518 3246 50 0000 L CNN
F 1 "500" H 5518 3155 50 0000 L CNN
F 2 "" V 5490 3190 50 0001 C CNN
F 3 "~" H 5450 3200 50 0001 C CNN
1 5450 3200
1 0 0 -1
$EndComp
$Comp
L Device:Crystal Y1
U 1 1 5D0074D0
P 4950 3200
F 0 "Y1" V 4996 3069 50 0000 R CNN
F 1 "Crystal" V 4905 3069 50 0000 R CNN
F 2 "" H 4950 3200 50 0001 C CNN
F 3 "~" H 4950 3200 50 0001 C CNN
1 4950 3200
0 -1 -1 0
$EndComp
$Comp
L power:VCC #PWR?
U 1 1 5D0081F3
P 5200 3750
F 0 "#PWR?" H 5200 3600 50 0001 C CNN
F 1 "VCC" H 5218 3923 50 0000 C CNN
F 2 "" H 5200 3750 50 0001 C CNN
F 3 "" H 5200 3750 50 0001 C CNN
1 5200 3750
-1 0 0 1
$EndComp
$Comp
L Device:R_US R1
U 1 1 5D01411B
P 8300 1800
F 0 "R1" V 8505 1800 50 0000 C CNN
F 1 "150" V 8414 1800 50 0000 C CNN
F 2 "" V 8340 1790 50 0001 C CNN
F 3 "~" H 8300 1800 50 0001 C CNN
1 8300 1800
0 -1 -1 0
$EndComp
$Comp
L Device:R_US R2
U 1 1 5D014636
P 8300 2200
F 0 "R2" V 8505 2200 50 0000 C CNN
F 1 "33" V 8414 2200 50 0000 C CNN
F 2 "" V 8340 2190 50 0001 C CNN
F 3 "~" H 8300 2200 50 0001 C CNN
1 8300 2200
0 -1 -1 0
$EndComp
$Comp
L Device:R_US R4
U 1 1 5D01DB0F
P 8300 2600
F 0 "R4" V 8505 2600 50 0000 C CNN
F 1 "33" V 8414 2600 50 0000 C CNN
F 2 "" V 8340 2590 50 0001 C CNN
F 3 "~" H 8300 2600 50 0001 C CNN
1 8300 2600
0 -1 -1 0
$EndComp
$Comp
L Device:R_US R5
U 1 1 5D01DE87
P 8300 3000
F 0 "R5" V 8505 3000 50 0000 C CNN
F 1 "150" V 8414 3000 50 0000 C CNN
F 2 "" V 8340 2990 50 0001 C CNN
F 3 "~" H 8300 3000 50 0001 C CNN
1 8300 3000
0 -1 -1 0
$EndComp
$Comp
L Device:R_US R3
U 1 1 5D026837
P 8550 2400
F 0 "R3" H 8618 2446 50 0000 L CNN
F 1 "510" H 8618 2355 50 0000 L CNN
F 2 "" V 8590 2390 50 0001 C CNN
F 3 "~" H 8550 2400 50 0001 C CNN
1 8550 2400
1 0 0 -1
$EndComp
Wire Wire Line
7850 1500 7850 2200
Wire Wire Line
7850 2200 8150 2200
Wire Wire Line
6250 2250 6050 2250
Wire Wire Line
6050 2250 6050 1400
Wire Wire Line
6050 1400 7950 1400
Wire Wire Line
7950 1400 7950 1800
Wire Wire Line
7950 1800 8150 1800
Wire Wire Line
7850 2600 8150 2600
Wire Wire Line
8450 1800 8550 1800
Wire Wire Line
8550 1800 8550 2200
Wire Wire Line
8450 3000 8550 3000
Wire Wire Line
8550 3000 8550 2600
Wire Wire Line
8450 2200 8550 2200
Connection ~ 8550 2200
Wire Wire Line
8550 2200 8550 2250
Wire Wire Line
8450 2600 8550 2600
Connection ~ 8550 2600
Wire Wire Line
8550 2600 8550 2550
Wire Wire Line
4950 2850 5600 2850
Wire Wire Line
5600 2850 5600 2050
Wire Wire Line
5600 2050 6250 2050
$Comp
L library:DS3487 U?
U 1 1 5D035700
P 7000 2400
F 0 "U?" H 7000 3115 50 0000 C CNN
F 1 "DS3487" H 7000 3024 50 0000 C CNN
F 2 "MODULE" H 7000 2400 50 0001 C CNN
F 3 "" H 7000 2400 50 0001 C CNN
1 7000 2400
1 0 0 -1
$EndComp
$Comp
L library:xxxx T1
U 1 1 5D03C013
P 9100 2700
F 0 "T1" H 9100 3381 50 0000 C CNN
F 1 "xxxx" H 9100 3290 50 0000 C CNN
F 2 "Transformer_SMD:Pulse_PA2002NL-PA2008NL-PA2009NL" H 9100 2700 50 0001 C CNN
F 3 "https://productfinder.pulseeng.com/products/datasheets/P663.pdf" H 8800 2700 50 0001 C CNN
1 9100 2700
-1 0 0 -1
$EndComp
Wire Wire Line
8550 2200 8900 2200
Wire Wire Line
8550 2600 8900 2600
$Comp
L Connector:Conn_Coaxial J1
U 1 1 5D047BD2
P 9700 2500
F 0 "J1" H 9800 2475 50 0000 L CNN
F 1 "RG62" H 9800 2384 50 0000 L CNN
F 2 "" H 9700 2500 50 0001 C CNN
F 3 " ~" H 9700 2500 50 0001 C CNN
1 9700 2500
1 0 0 -1
$EndComp
Wire Wire Line
9700 2700 9700 2900
Wire Wire Line
9700 2900 9450 2900
Wire Wire Line
9300 2500 9450 2500
$Comp
L Device:R_US R6
U 1 1 5D04B24C
P 9450 2700
F 0 "R6" H 9518 2746 50 0000 L CNN
F 1 "120" H 9518 2655 50 0000 L CNN
F 2 "" V 9490 2690 50 0001 C CNN
F 3 "~" H 9450 2700 50 0001 C CNN
1 9450 2700
1 0 0 -1
$EndComp
Wire Wire Line
9450 2550 9450 2500
Connection ~ 9450 2500
Wire Wire Line
9450 2500 9500 2500
Wire Wire Line
9450 2850 9450 2900
Connection ~ 9450 2900
Wire Wire Line
9450 2900 9300 2900
$Comp
L power:GND #PWR?
U 1 1 5D04EB7E
P 6250 3000
F 0 "#PWR?" H 6250 2750 50 0001 C CNN
F 1 "GND" H 6255 2827 50 0000 C CNN
F 2 "" H 6250 3000 50 0001 C CNN
F 3 "" H 6250 3000 50 0001 C CNN
1 6250 3000
1 0 0 -1
$EndComp
$Comp
L power:GND #PWR?
U 1 1 5D051C9E
P 3450 3350
F 0 "#PWR?" H 3450 3100 50 0001 C CNN
F 1 "GND" H 3455 3177 50 0000 C CNN
F 2 "" H 3450 3350 50 0001 C CNN
F 3 "" H 3450 3350 50 0001 C CNN
1 3450 3350
1 0 0 -1
$EndComp
Wire Wire Line
3450 3350 3450 3050
$Comp
L Device:C C1
U 1 1 5D05AC0A
P 5200 3600
F 0 "C1" H 5315 3646 50 0000 L CNN
F 1 "30 pF" H 5315 3555 50 0000 L CNN
F 2 "" H 5238 3450 50 0001 C CNN
F 3 "~" H 5200 3600 50 0001 C CNN
1 5200 3600
1 0 0 -1
$EndComp
$Comp
L library:DP8341 U2
U 1 1 5D0650F6
P 4200 5100
F 0 "U2" H 4200 4185 50 0000 C CNN
F 1 "DP8341" H 4200 4276 50 0000 C CNN
F 2 "MODULE" H 4200 5100 50 0001 C CNN
F 3 "" H 4200 5100 50 0001 C CNN
1 4200 5100
-1 0 0 1
$EndComp
Wire Wire Line
4950 5550 8700 5550
Wire Wire Line
8700 2800 8900 2800
Wire Wire Line
4950 5450 8800 5450
Wire Wire Line
8800 3200 8900 3200
Wire Wire Line
4950 5650 5750 5650
Wire Wire Line
3450 2950 3200 2950
Wire Wire Line
3200 4050 5250 4050
Wire Wire Line
5250 4050 5250 5150
Wire Wire Line
5250 5150 4950 5150
Wire Wire Line
3450 4650 3100 4650
Wire Wire Line
3100 2850 3450 2850
Wire Wire Line
3450 4750 3000 4750
Wire Wire Line
3000 2750 3450 2750
Wire Wire Line
3450 4850 2900 4850
Wire Wire Line
2900 2650 3450 2650
Wire Wire Line
3450 4950 2800 4950
Wire Wire Line
2800 2550 3450 2550
Wire Wire Line
3450 2450 2700 2450
Wire Wire Line
2700 5050 3450 5050
Wire Wire Line
3450 2350 2600 2350
Wire Wire Line
2600 5150 3450 5150
Wire Wire Line
3450 2250 2500 2250
Wire Wire Line
2500 5250 3450 5250
Wire Wire Line
3450 2150 2400 2150
Wire Wire Line
2400 5350 3450 5350
Wire Wire Line
3450 2050 2300 2050
Wire Wire Line
2300 5450 3450 5450
Wire Wire Line
3450 1950 2200 1950
Wire Wire Line
2200 5550 3450 5550
Text GLabel 1100 5550 0 50 Input ~ 0
MEGA22
Wire Wire Line
1100 5550 2200 5550
Connection ~ 2200 5550
Text GLabel 1100 5450 0 50 Input ~ 0
MEGA23
Wire Wire Line
1100 5450 2300 5450
Connection ~ 2300 5450
Text GLabel 1100 5350 0 50 Input ~ 0
MEGA24
Text GLabel 1100 5250 0 50 Input ~ 0
MEGA25
Text GLabel 1100 5150 0 50 Input ~ 0
MEGA26
Text GLabel 1100 5050 0 50 Input ~ 0
MEGA27
Text GLabel 1100 4950 0 50 Input ~ 0
MEGA28
Text GLabel 1100 4850 0 50 Input ~ 0
MEGA29
Text GLabel 1100 4750 0 50 Input ~ 0
MEGA37
Text GLabel 1100 4650 0 50 Input ~ 0
MEGA36
Wire Wire Line
1100 4650 3100 4650
Connection ~ 3100 4650
Wire Wire Line
1100 4750 3000 4750
Connection ~ 3000 4750
Wire Wire Line
1100 4850 2900 4850
Connection ~ 2900 4850
Wire Wire Line
1100 4950 2800 4950
Connection ~ 2800 4950
Wire Wire Line
1100 5050 2700 5050
Connection ~ 2700 5050
Wire Wire Line
1100 5150 2600 5150
Connection ~ 2600 5150
Wire Wire Line
1100 5250 2500 5250
Connection ~ 2500 5250
Wire Wire Line
1100 5350 2400 5350
Connection ~ 2400 5350
Text GLabel 1050 4550 0 50 Input ~ 0
MEGA7
Wire Wire Line
1050 4550 3450 4550
Text GLabel 6100 4750 2 50 Input ~ 0
MEGA2
Text GLabel 6100 4950 2 50 Input ~ 0
MEGA3
Text GLabel 6100 4850 2 50 Input ~ 0
MEGA5
Text GLabel 6100 5250 2 50 Input ~ 0
MEGA4
Text GLabel 6100 4650 2 50 Input ~ 0
MEGA6
Wire Wire Line
4950 4650 6100 4650
Wire Wire Line
4950 4750 6100 4750
Wire Wire Line
4950 4850 6100 4850
Wire Wire Line
4950 4950 6100 4950
Wire Wire Line
4950 5250 6100 5250
$Comp
L power:GND #PWR?
U 1 1 5D0CF15F
P 4950 4350
F 0 "#PWR?" H 4950 4100 50 0001 C CNN
F 1 "GND" H 4955 4177 50 0000 C CNN
F 2 "" H 4950 4350 50 0001 C CNN
F 3 "" H 4950 4350 50 0001 C CNN
1 4950 4350
-1 0 0 1
$EndComp
Wire Wire Line
4950 4350 4950 4550
Text GLabel 6100 5050 2 50 Input ~ 0
MEGA18
Wire Wire Line
4950 5050 6100 5050
Text GLabel 5050 1050 1 50 Input ~ 0
MEGA8
Text GLabel 5150 1050 1 50 Input ~ 0
META9
Text GLabel 5250 1050 1 50 Input ~ 0
MEGA10
Text GLabel 5450 1050 1 50 Input ~ 0
MEGA11
Text GLabel 5350 1050 1 50 Input ~ 0
MEGA12
Wire Wire Line
4950 2150 5150 2150
Wire Wire Line
5150 2150 5150 1050
Wire Wire Line
4950 2250 5250 2250
Wire Wire Line
5250 2250 5250 1050
Wire Wire Line
5350 1050 5350 2450
Wire Wire Line
5350 2450 4950 2450
Wire Wire Line
4950 2550 5450 2550
Wire Wire Line
5450 2550 5450 1050
Wire Wire Line
4950 2050 5050 2050
Wire Wire Line
5050 2050 5050 1050
$Comp
L power:VCC #PWR?
U 1 1 5D110504
P 3450 5900
F 0 "#PWR?" H 3450 5750 50 0001 C CNN
F 1 "VCC" H 3468 6073 50 0000 C CNN
F 2 "" H 3450 5900 50 0001 C CNN
F 3 "" H 3450 5900 50 0001 C CNN
1 3450 5900
-1 0 0 1
$EndComp
Wire Wire Line
3450 5650 3450 5900
$Comp
L power:VCC #PWR?
U 1 1 5D118163
P 4950 1600
F 0 "#PWR?" H 4950 1450 50 0001 C CNN
F 1 "VCC" H 4967 1773 50 0000 C CNN
F 2 "" H 4950 1600 50 0001 C CNN
F 3 "" H 4950 1600 50 0001 C CNN
1 4950 1600
1 0 0 -1
$EndComp
Wire Wire Line
4950 1600 4950 1950
Wire Wire Line
4950 2950 5450 2950
Wire Wire Line
5450 2950 5450 3050
Wire Wire Line
4950 2350 5750 2350
Wire Wire Line
4950 3350 4950 3450
Wire Wire Line
4950 3450 5200 3450
Wire Wire Line
5200 3450 5450 3450
Wire Wire Line
5450 3450 5450 3350
Connection ~ 5200 3450
Wire Wire Line
4950 2650 6250 2650
Wire Wire Line
5750 5650 5750 2350
Connection ~ 5750 2350
Wire Wire Line
5750 2350 6250 2350
Wire Wire Line
3200 2950 3200 4050
Wire Wire Line
3100 2850 3100 4650
Wire Wire Line
3000 2750 3000 4750
Wire Wire Line
2900 2650 2900 4850
Wire Wire Line
2800 2550 2800 4950
Wire Wire Line
2700 2450 2700 5050
Wire Wire Line
2600 2350 2600 5150
Wire Wire Line
2500 2250 2500 5250
Wire Wire Line
2400 2150 2400 5350
Wire Wire Line
2300 2050 2300 5450
Wire Wire Line
2200 1950 2200 5550
Wire Wire Line
8700 2800 8700 5550
Wire Wire Line
8800 3200 8800 5450
$Comp
L power:VCC #PWR?
U 1 1 5D1B82CE
P 7750 1750
F 0 "#PWR?" H 7750 1600 50 0001 C CNN
F 1 "VCC" H 7767 1923 50 0000 C CNN
F 2 "" H 7750 1750 50 0001 C CNN
F 3 "" H 7750 1750 50 0001 C CNN
1 7750 1750
1 0 0 -1
$EndComp
Wire Wire Line
6250 2750 6250 3000
Wire Wire Line
7850 3300 6050 3300
Wire Wire Line
6050 3300 6050 2550
Wire Wire Line
6050 2550 6250 2550
Wire Wire Line
7850 2600 7850 3300
Wire Wire Line
6250 2450 6150 2450
Wire Wire Line
6150 2450 6150 1500
Wire Wire Line
6150 1500 7850 1500
Wire Wire Line
6250 2150 5950 2150
Wire Wire Line
5950 2150 5950 3400
Wire Wire Line
5950 3400 7950 3400
Wire Wire Line
7950 3400 7950 3000
Wire Wire Line
7950 3000 8150 3000
Wire Wire Line
7750 1750 7750 2050
$EndSCHEMATC

View File

@@ -0,0 +1 @@
(kicad_pcb (version 4) (host kicad "dummy file") )

View File

@@ -0,0 +1,33 @@
update=22/05/2015 07:44:53
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[pcbnew]
version=1
LastNetListRead=
UseCmpFile=1
PadDrill=0.600000000000
PadDrillOvalY=0.600000000000
PadSizeH=1.500000000000
PadSizeV=1.500000000000
PcbTextSizeV=1.500000000000
PcbTextSizeH=1.500000000000
PcbTextThickness=0.300000000000
ModuleTextSizeV=1.000000000000
ModuleTextSizeH=1.000000000000
ModuleTextSizeThickness=0.150000000000
SolderMaskClearance=0.000000000000
SolderMaskMinWidth=0.000000000000
DrawSegmentWidth=0.200000000000
BoardOutlineThickness=0.100000000000
ModuleOutlineThickness=0.150000000000
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]

View File

@@ -0,0 +1,557 @@
EESchema Schematic File Version 4
EELAYER 29 0
EELAYER END
$Descr USLetter 11000 8500
encoding utf-8
Sheet 1 1
Title ""
Date ""
Rev ""
Comp ""
Comment1 ""
Comment2 ""
Comment3 ""
Comment4 "Based on the typical application from the DP8340 and DP8341 data sheets"
$EndDescr
$Comp
L library:DP8340 U1
U 1 1 5CFF4259
P 4200 2500
F 0 "U1" H 4200 3415 50 0000 C CNN
F 1 "DP8340" H 4200 3324 50 0000 C CNN
F 2 "MODULE" H 4200 2500 50 0001 C CNN
F 3 "" H 4200 2500 50 0001 C CNN
1 4200 2500
1 0 0 -1
$EndComp
$Comp
L Device:R_US R7
U 1 1 5D005C33
P 5450 3200
F 0 "R7" H 5518 3246 50 0000 L CNN
F 1 "500" H 5518 3155 50 0000 L CNN
F 2 "" V 5490 3190 50 0001 C CNN
F 3 "~" H 5450 3200 50 0001 C CNN
1 5450 3200
1 0 0 -1
$EndComp
$Comp
L Device:Crystal Y1
U 1 1 5D0074D0
P 4950 3200
F 0 "Y1" V 4996 3069 50 0000 R CNN
F 1 "Crystal" V 4905 3069 50 0000 R CNN
F 2 "" H 4950 3200 50 0001 C CNN
F 3 "~" H 4950 3200 50 0001 C CNN
1 4950 3200
0 -1 -1 0
$EndComp
$Comp
L power:VCC #PWR?
U 1 1 5D0081F3
P 5200 3750
F 0 "#PWR?" H 5200 3600 50 0001 C CNN
F 1 "VCC" H 5218 3923 50 0000 C CNN
F 2 "" H 5200 3750 50 0001 C CNN
F 3 "" H 5200 3750 50 0001 C CNN
1 5200 3750
-1 0 0 1
$EndComp
$Comp
L Device:R_US R1
U 1 1 5D01411B
P 8300 1800
F 0 "R1" V 8505 1800 50 0000 C CNN
F 1 "150" V 8414 1800 50 0000 C CNN
F 2 "" V 8340 1790 50 0001 C CNN
F 3 "~" H 8300 1800 50 0001 C CNN
1 8300 1800
0 -1 -1 0
$EndComp
$Comp
L Device:R_US R2
U 1 1 5D014636
P 8300 2200
F 0 "R2" V 8505 2200 50 0000 C CNN
F 1 "33" V 8414 2200 50 0000 C CNN
F 2 "" V 8340 2190 50 0001 C CNN
F 3 "~" H 8300 2200 50 0001 C CNN
1 8300 2200
0 -1 -1 0
$EndComp
$Comp
L Device:R_US R4
U 1 1 5D01DB0F
P 8300 2600
F 0 "R4" V 8505 2600 50 0000 C CNN
F 1 "33" V 8414 2600 50 0000 C CNN
F 2 "" V 8340 2590 50 0001 C CNN
F 3 "~" H 8300 2600 50 0001 C CNN
1 8300 2600
0 -1 -1 0
$EndComp
$Comp
L Device:R_US R5
U 1 1 5D01DE87
P 8300 3000
F 0 "R5" V 8505 3000 50 0000 C CNN
F 1 "150" V 8414 3000 50 0000 C CNN
F 2 "" V 8340 2990 50 0001 C CNN
F 3 "~" H 8300 3000 50 0001 C CNN
1 8300 3000
0 -1 -1 0
$EndComp
$Comp
L Device:R_US R3
U 1 1 5D026837
P 8550 2400
F 0 "R3" H 8618 2446 50 0000 L CNN
F 1 "510" H 8618 2355 50 0000 L CNN
F 2 "" V 8590 2390 50 0001 C CNN
F 3 "~" H 8550 2400 50 0001 C CNN
1 8550 2400
1 0 0 -1
$EndComp
Wire Wire Line
7850 1500 7850 2200
Wire Wire Line
7850 2200 8150 2200
Wire Wire Line
6250 2250 6050 2250
Wire Wire Line
6050 2250 6050 1400
Wire Wire Line
6050 1400 7950 1400
Wire Wire Line
7950 1400 7950 1800
Wire Wire Line
7950 1800 8150 1800
Wire Wire Line
7850 2600 8150 2600
Wire Wire Line
8450 1800 8550 1800
Wire Wire Line
8550 1800 8550 2200
Wire Wire Line
8450 3000 8550 3000
Wire Wire Line
8550 3000 8550 2600
Wire Wire Line
8450 2200 8550 2200
Connection ~ 8550 2200
Wire Wire Line
8550 2200 8550 2250
Wire Wire Line
8450 2600 8550 2600
Connection ~ 8550 2600
Wire Wire Line
8550 2600 8550 2550
Wire Wire Line
4950 2850 5600 2850
Wire Wire Line
5600 2850 5600 2050
Wire Wire Line
5600 2050 6250 2050
$Comp
L library:DS3487 U3
U 1 1 5D035700
P 7000 2400
F 0 "U3" H 7000 3115 50 0000 C CNN
F 1 "DS3487" H 7000 3024 50 0000 C CNN
F 2 "MODULE" H 7000 2400 50 0001 C CNN
F 3 "" H 7000 2400 50 0001 C CNN
1 7000 2400
1 0 0 -1
$EndComp
$Comp
L library:xxxx T1
U 1 1 5D03C013
P 9100 2700
F 0 "T1" H 9100 3381 50 0000 C CNN
F 1 "PE-5762" H 9100 3290 50 0000 C CNN
F 2 "Transformer_SMD:Pulse_PA2002NL-PA2008NL-PA2009NL" H 9100 2700 50 0001 C CNN
F 3 "https://productfinder.pulseeng.com/products/datasheets/P663.pdf" H 8800 2700 50 0001 C CNN
1 9100 2700
-1 0 0 -1
$EndComp
Wire Wire Line
8550 2200 8900 2200
Wire Wire Line
8550 2600 8900 2600
$Comp
L Connector:Conn_Coaxial J1
U 1 1 5D047BD2
P 9700 2500
F 0 "J1" H 9800 2475 50 0000 L CNN
F 1 "RG62" H 9800 2384 50 0000 L CNN
F 2 "" H 9700 2500 50 0001 C CNN
F 3 " ~" H 9700 2500 50 0001 C CNN
1 9700 2500
1 0 0 -1
$EndComp
Wire Wire Line
9700 2700 9700 2900
Wire Wire Line
9700 2900 9450 2900
Wire Wire Line
9300 2500 9450 2500
$Comp
L Device:R_US R6
U 1 1 5D04B24C
P 9450 2700
F 0 "R6" H 9518 2746 50 0000 L CNN
F 1 "120" H 9518 2655 50 0000 L CNN
F 2 "" V 9490 2690 50 0001 C CNN
F 3 "~" H 9450 2700 50 0001 C CNN
1 9450 2700
1 0 0 -1
$EndComp
Wire Wire Line
9450 2550 9450 2500
Connection ~ 9450 2500
Wire Wire Line
9450 2500 9500 2500
Wire Wire Line
9450 2850 9450 2900
Connection ~ 9450 2900
Wire Wire Line
9450 2900 9300 2900
$Comp
L power:GND #PWR?
U 1 1 5D04EB7E
P 6250 3000
F 0 "#PWR?" H 6250 2750 50 0001 C CNN
F 1 "GND" H 6255 2827 50 0000 C CNN
F 2 "" H 6250 3000 50 0001 C CNN
F 3 "" H 6250 3000 50 0001 C CNN
1 6250 3000
1 0 0 -1
$EndComp
$Comp
L power:GND #PWR?
U 1 1 5D051C9E
P 3450 3350
F 0 "#PWR?" H 3450 3100 50 0001 C CNN
F 1 "GND" H 3455 3177 50 0000 C CNN
F 2 "" H 3450 3350 50 0001 C CNN
F 3 "" H 3450 3350 50 0001 C CNN
1 3450 3350
1 0 0 -1
$EndComp
Wire Wire Line
3450 3350 3450 3050
$Comp
L Device:C C1
U 1 1 5D05AC0A
P 5200 3600
F 0 "C1" H 5315 3646 50 0000 L CNN
F 1 "30 pF" H 5315 3555 50 0000 L CNN
F 2 "" H 5238 3450 50 0001 C CNN
F 3 "~" H 5200 3600 50 0001 C CNN
1 5200 3600
1 0 0 -1
$EndComp
$Comp
L library:DP8341 U2
U 1 1 5D0650F6
P 4200 5100
F 0 "U2" H 4200 4185 50 0000 C CNN
F 1 "DP8341" H 4200 4276 50 0000 C CNN
F 2 "MODULE" H 4200 5100 50 0001 C CNN
F 3 "" H 4200 5100 50 0001 C CNN
1 4200 5100
-1 0 0 1
$EndComp
Wire Wire Line
4950 5550 8700 5550
Wire Wire Line
8700 2800 8900 2800
Wire Wire Line
4950 5450 8800 5450
Wire Wire Line
8800 3200 8900 3200
Wire Wire Line
4950 5650 5750 5650
Wire Wire Line
3450 2950 3200 2950
Wire Wire Line
3200 4050 5250 4050
Wire Wire Line
5250 4050 5250 5150
Wire Wire Line
5250 5150 4950 5150
Wire Wire Line
3450 4650 3100 4650
Wire Wire Line
3100 2850 3450 2850
Wire Wire Line
3450 4750 3000 4750
Wire Wire Line
3000 2750 3450 2750
Wire Wire Line
3450 4850 2900 4850
Wire Wire Line
2900 2650 3450 2650
Wire Wire Line
3450 4950 2800 4950
Wire Wire Line
2800 2550 3450 2550
Wire Wire Line
3450 2450 2700 2450
Wire Wire Line
2700 5050 3450 5050
Wire Wire Line
3450 2350 2600 2350
Wire Wire Line
2600 5150 3450 5150
Wire Wire Line
3450 2250 2500 2250
Wire Wire Line
2500 5250 3450 5250
Wire Wire Line
3450 2150 2400 2150
Wire Wire Line
2400 5350 3450 5350
Wire Wire Line
3450 2050 2300 2050
Wire Wire Line
2300 5450 3450 5450
Wire Wire Line
3450 1950 2200 1950
Wire Wire Line
2200 5550 3450 5550
Text GLabel 1100 5550 0 50 Input ~ 0
MEGA22
Wire Wire Line
1100 5550 2200 5550
Connection ~ 2200 5550
Text GLabel 1100 5450 0 50 Input ~ 0
MEGA23
Wire Wire Line
1100 5450 2300 5450
Connection ~ 2300 5450
Text GLabel 1100 5350 0 50 Input ~ 0
MEGA24
Text GLabel 1100 5250 0 50 Input ~ 0
MEGA25
Text GLabel 1100 5150 0 50 Input ~ 0
MEGA26
Text GLabel 1100 5050 0 50 Input ~ 0
MEGA27
Text GLabel 1100 4950 0 50 Input ~ 0
MEGA28
Text GLabel 1100 4850 0 50 Input ~ 0
MEGA29
Text GLabel 1100 4750 0 50 Input ~ 0
MEGA37
Text GLabel 1100 4650 0 50 Input ~ 0
MEGA36
Wire Wire Line
1100 4650 3100 4650
Connection ~ 3100 4650
Wire Wire Line
1100 4750 3000 4750
Connection ~ 3000 4750
Wire Wire Line
1100 4850 2900 4850
Connection ~ 2900 4850
Wire Wire Line
1100 4950 2800 4950
Connection ~ 2800 4950
Wire Wire Line
1100 5050 2700 5050
Connection ~ 2700 5050
Wire Wire Line
1100 5150 2600 5150
Connection ~ 2600 5150
Wire Wire Line
1100 5250 2500 5250
Connection ~ 2500 5250
Wire Wire Line
1100 5350 2400 5350
Connection ~ 2400 5350
Text GLabel 1050 4550 0 50 Input ~ 0
MEGA7
Wire Wire Line
1050 4550 3450 4550
Text GLabel 6100 4750 2 50 Input ~ 0
MEGA2
Text GLabel 6100 4950 2 50 Input ~ 0
MEGA3
Text GLabel 6100 4850 2 50 Input ~ 0
MEGA5
Text GLabel 6100 5250 2 50 Input ~ 0
MEGA4
Text GLabel 6100 4650 2 50 Input ~ 0
MEGA6
Wire Wire Line
4950 4650 6100 4650
Wire Wire Line
4950 4750 6100 4750
Wire Wire Line
4950 4850 6100 4850
Wire Wire Line
4950 4950 6100 4950
Wire Wire Line
4950 5250 6100 5250
$Comp
L power:GND #PWR?
U 1 1 5D0CF15F
P 4950 4350
F 0 "#PWR?" H 4950 4100 50 0001 C CNN
F 1 "GND" H 4955 4177 50 0000 C CNN
F 2 "" H 4950 4350 50 0001 C CNN
F 3 "" H 4950 4350 50 0001 C CNN
1 4950 4350
-1 0 0 1
$EndComp
Wire Wire Line
4950 4350 4950 4550
Text GLabel 6100 5050 2 50 Input ~ 0
MEGA18
Wire Wire Line
4950 5050 6100 5050
Text GLabel 5050 1050 1 50 Input ~ 0
MEGA8
Text GLabel 5150 1050 1 50 Input ~ 0
META9
Text GLabel 5250 1050 1 50 Input ~ 0
MEGA10
Text GLabel 5450 1050 1 50 Input ~ 0
MEGA11
Text GLabel 5350 1050 1 50 Input ~ 0
MEGA12
Wire Wire Line
4950 2150 5150 2150
Wire Wire Line
5150 2150 5150 1050
Wire Wire Line
4950 2250 5250 2250
Wire Wire Line
5250 2250 5250 1050
Wire Wire Line
5350 1050 5350 2450
Wire Wire Line
5350 2450 4950 2450
Wire Wire Line
4950 2550 5450 2550
Wire Wire Line
5450 2550 5450 1050
Wire Wire Line
4950 2050 5050 2050
Wire Wire Line
5050 2050 5050 1050
$Comp
L power:VCC #PWR?
U 1 1 5D110504
P 3450 5900
F 0 "#PWR?" H 3450 5750 50 0001 C CNN
F 1 "VCC" H 3468 6073 50 0000 C CNN
F 2 "" H 3450 5900 50 0001 C CNN
F 3 "" H 3450 5900 50 0001 C CNN
1 3450 5900
-1 0 0 1
$EndComp
Wire Wire Line
3450 5650 3450 5900
$Comp
L power:VCC #PWR?
U 1 1 5D118163
P 4950 1600
F 0 "#PWR?" H 4950 1450 50 0001 C CNN
F 1 "VCC" H 4967 1773 50 0000 C CNN
F 2 "" H 4950 1600 50 0001 C CNN
F 3 "" H 4950 1600 50 0001 C CNN
1 4950 1600
1 0 0 -1
$EndComp
Wire Wire Line
4950 1600 4950 1950
Wire Wire Line
4950 2950 5450 2950
Wire Wire Line
5450 2950 5450 3050
Wire Wire Line
4950 2350 5750 2350
Wire Wire Line
4950 3350 4950 3450
Wire Wire Line
4950 3450 5200 3450
Wire Wire Line
5200 3450 5450 3450
Wire Wire Line
5450 3450 5450 3350
Connection ~ 5200 3450
Wire Wire Line
4950 2650 6250 2650
Wire Wire Line
5750 5650 5750 2350
Connection ~ 5750 2350
Wire Wire Line
5750 2350 6250 2350
Wire Wire Line
3200 2950 3200 4050
Wire Wire Line
3100 2850 3100 4650
Wire Wire Line
3000 2750 3000 4750
Wire Wire Line
2900 2650 2900 4850
Wire Wire Line
2800 2550 2800 4950
Wire Wire Line
2700 2450 2700 5050
Wire Wire Line
2600 2350 2600 5150
Wire Wire Line
2500 2250 2500 5250
Wire Wire Line
2400 2150 2400 5350
Wire Wire Line
2300 2050 2300 5450
Wire Wire Line
2200 1950 2200 5550
Wire Wire Line
8700 2800 8700 5550
Wire Wire Line
8800 3200 8800 5450
$Comp
L power:VCC #PWR?
U 1 1 5D1B82CE
P 7750 1750
F 0 "#PWR?" H 7750 1600 50 0001 C CNN
F 1 "VCC" H 7767 1923 50 0000 C CNN
F 2 "" H 7750 1750 50 0001 C CNN
F 3 "" H 7750 1750 50 0001 C CNN
1 7750 1750
1 0 0 -1
$EndComp
Wire Wire Line
6250 2750 6250 3000
Wire Wire Line
7850 3300 6050 3300
Wire Wire Line
6050 3300 6050 2550
Wire Wire Line
6050 2550 6250 2550
Wire Wire Line
7850 2600 7850 3300
Wire Wire Line
6250 2450 6150 2450
Wire Wire Line
6150 2450 6150 1500
Wire Wire Line
6150 1500 7850 1500
Wire Wire Line
6250 2150 5950 2150
Wire Wire Line
5950 2150 5950 3400
Wire Wire Line
5950 3400 7950 3400
Wire Wire Line
7950 3400 7950 3000
Wire Wire Line
7950 3000 8150 3000
Wire Wire Line
7750 1750 7750 2050
$EndSCHEMATC

View File

@@ -0,0 +1,9 @@
EESchema-DOCLIB Version 2.0
#
$CMP xxxx
D xxxx
K pulse
F https://productfinder.pulseeng.com/products/datasheets/P663.pdf
$ENDCMP
#
#End Doc Library

View File

@@ -0,0 +1,9 @@
EESchema-DOCLIB Version 2.0
#
$CMP xxxx
D xxxx
K pulse
F https://productfinder.pulseeng.com/products/datasheets/P663.pdf
$ENDCMP
#
#End Doc Library

View File

@@ -0,0 +1,144 @@
EESchema-LIBRARY Version 2.4
#encoding utf-8
#
# DP8340
#
DEF DP8340 U 0 40 Y Y 1 F N
F0 "U" 0 -100 50 H V C CNN
F1 "DP8340" 0 100 50 H V C CNN
F2 "MODULE" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
S -450 -750 450 750 1 0 0 N
X DI11 1 -750 550 300 R 50 50 1 1 U
X DI2 10 -750 -350 300 R 50 50 1 1 U
X CLK_OUT 11 -750 -450 300 R 50 50 1 1 U
X GND 12 -750 -550 300 R 50 50 1 1 U
X X1 13 750 -550 300 L 50 50 1 1 U
X X2 14 750 -450 300 L 50 50 1 1 U
X DATA_DLY 15 750 -350 300 L 50 50 1 1 U
X DATA_OUT1 16 750 -250 300 L 50 50 1 1 U
X DATA_OUT2 17 750 -150 300 L 50 50 1 1 U
X EVEN_ODD 18 750 -50 300 L 50 50 1 1 U
X PARITY_CTL 19 750 50 300 L 50 50 1 1 U
X DI10 2 -750 450 300 R 50 50 1 1 U
X TX_ACTIVE 20 750 150 300 L 50 50 1 1 U
X AUTO_RESP 21 750 250 300 L 50 50 1 1 U
X REG_FULL 22 750 350 300 L 50 50 1 1 U
X REG_LOAD 23 750 450 300 L 50 50 1 1 U
X VCC 24 750 550 300 L 50 50 1 1 U
X DI9 3 -750 350 300 R 50 50 1 1 U
X DI8 4 -750 250 300 R 50 50 1 1 U
X DI7 5 -750 150 300 R 50 50 1 1 U
X DI6 6 -750 50 300 R 50 50 1 1 U
X DI5 7 -750 -50 300 R 50 50 1 1 U
X DI4 8 -750 -150 300 R 50 50 1 1 U
X DI3 9 -750 -250 300 R 50 50 1 1 U
ENDDRAW
ENDDEF
#
# DP8341
#
DEF DP8341 U 0 40 Y Y 1 F N
F0 "U" 0 -100 50 H V C CNN
F1 "DP8341" 0 100 50 H V C CNN
F2 "MODULE" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
S -450 -750 450 750 1 0 0 N
X RX_DISABLE 1 -750 550 300 R 50 50 1 1 U
X DATA_AVAIL 10 -750 -350 300 R 50 50 1 1 U
X OUTPUT_CTL 11 -750 -450 300 R 50 50 1 1 U
X GND 12 -750 -550 300 R 50 50 1 1 U
X OUTPUT_EN 13 750 -550 300 L 50 50 1 1 U
X DO2 14 750 -450 300 L 50 50 1 1 U
X DO3 15 750 -350 300 L 50 50 1 1 U
X DO4 16 750 -250 300 L 50 50 1 1 U
X DO5 17 750 -150 300 L 50 50 1 1 U
X DO6 18 750 -50 300 L 50 50 1 1 U
X DO7 19 750 50 300 L 50 50 1 1 U
X +AMP_IN 2 -750 450 300 R 50 50 1 1 U
X DO8 20 750 150 300 L 50 50 1 1 U
X DO9 21 750 250 300 L 50 50 1 1 U
X DO10 22 750 350 300 L 50 50 1 1 U
X DO11 23 750 450 300 L 50 50 1 1 U
X VCC 24 750 550 300 L 50 50 1 1 U
X -AMP_IN 3 -750 350 300 R 50 50 1 1 U
X DATA 4 -750 250 300 R 50 50 1 1 U
X DATA_CTL 5 -750 150 300 R 50 50 1 1 U
X CLOCK 6 -750 50 300 R 50 50 1 1 U
X RX_ACTIVE 7 -750 -50 300 R 50 50 1 1 U
X ERROR 8 -750 -150 300 R 50 50 1 1 U
X REG_READ 9 -750 -250 300 R 50 50 1 1 U
ENDDRAW
ENDDEF
#
# DS3487
#
DEF DS3487 U 0 40 Y Y 1 F N
F0 "U" 0 -100 50 H V C CNN
F1 "DS3487" 0 100 50 H V C CNN
F2 "MODULE" 0 0 50 H I C CNN
F3 "DOCUMENTATION" 0 0 50 H I C CNN
DRAW
S -450 -550 450 550 1 0 0 N
X PIN1 1 -750 350 300 R 50 50 1 1 U
X PIN10 10 750 -250 300 L 50 50 1 1 U
X PIN11 11 750 -150 300 L 50 50 1 1 U
X PIN12 12 750 -50 300 L 50 50 1 1 U
X PIN13 13 750 50 300 L 50 50 1 1 U
X PIN14 14 750 150 300 L 50 50 1 1 U
X PIN15 15 750 250 300 L 50 50 1 1 U
X PIN16 16 750 350 300 L 50 50 1 1 U
X PIN2 2 -750 250 300 R 50 50 1 1 U
X PIN3 3 -750 150 300 R 50 50 1 1 U
X PIN4 4 -750 50 300 R 50 50 1 1 U
X PIN5 5 -750 -50 300 R 50 50 1 1 U
X PIN6 6 -750 -150 300 R 50 50 1 1 U
X PIN7 7 -750 -250 300 R 50 50 1 1 U
X PIN8 8 -750 -350 300 R 50 50 1 1 U
X PIN9 9 750 -350 300 L 50 50 1 1 U
ENDDRAW
ENDDEF
#
# xxxx
#
DEF xxxx T 0 20 Y N 1 F N
F0 "T" 0 550 50 H V C CNN
F1 "xxxx" 0 -550 50 H V C CNN
F2 "Transformer_SMD:Pulse_PA2002NL-PA2008NL-PA2009NL" 0 0 50 H I C CNN
F3 "" -300 0 50 H I C CNN
DRAW
A -100 -90 30 900 -900 0 1 8 N -100 -60 -100 -120
A -100 -30 30 900 -900 0 1 8 N -100 0 -100 -60
A -100 30 30 900 -900 0 1 8 N -100 60 -100 0
A 100 -390 30 -900 900 0 1 8 N 100 -420 100 -360
A 100 -330 30 -900 900 0 1 8 N 100 -360 100 -300
A 100 -270 30 -900 900 0 1 8 N 100 -300 100 -240
A 100 -210 30 -900 900 0 1 8 N 100 -240 100 -180
A 100 210 30 -900 900 0 1 8 N 100 180 100 240
A 100 270 30 -900 900 0 1 8 N 100 240 100 300
A 100 330 30 -900 900 0 1 8 N 100 300 100 360
A 100 390 30 -900 900 0 1 8 N 100 360 100 420
A -100 90 30 900 -900 1 1 8 N -100 120 -100 60
C -100 90 10 0 1 0 F
C 100 -210 10 0 1 0 F
C 100 390 10 0 1 0 F
P 2 0 1 0 -100 -120 -100 -200 N
P 2 0 1 0 -100 200 -100 120 N
P 2 0 1 0 -25 425 -25 -425 N
P 2 0 1 0 25 425 25 -425 N
P 2 0 1 0 100 -420 100 -500 N
P 2 0 1 0 100 -100 100 -180 N
P 2 0 1 0 100 180 100 100 N
P 2 0 1 0 100 500 100 420 N
X ~ 1 200 500 100 L 50 50 1 1 P
X ~ 2 200 100 100 L 50 50 1 1 P
X ~ 3 -200 200 100 R 50 50 1 1 P
X ~ 4 -200 -200 100 R 50 50 1 1 P
X ~ 5 200 -100 100 L 50 50 1 1 P
X ~ 6 200 -500 100 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
#End Library

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 216 KiB

View File

@@ -0,0 +1,3 @@
(sym_lib_table
(lib (name library)(type Legacy)(uri ${KIPRJMOD}/library.lib)(options "")(descr ""))
)

112
pycoax/.gitignore vendored Normal file
View File

@@ -0,0 +1,112 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
VIRTUALENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json

13
pycoax/LICENSE Normal file
View File

@@ -0,0 +1,13 @@
Copyright (c) 2019, Andrew Kay
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

9
pycoax/README.md Normal file
View File

@@ -0,0 +1,9 @@
# pycoax
Python IBM 3270 coaxial interface library.
## Use
You will need to build a [interface](../interface1) and connect it to your computer.
See [examples](examples) for complete examples.

1
pycoax/coax/__about__.py Normal file
View File

@@ -0,0 +1 @@
__version__ = '0.1.0'

39
pycoax/coax/__init__.py Normal file
View File

@@ -0,0 +1,39 @@
from .__about__ import __version__
from .interface1 import Interface1
from .protocol import (
PollResponse,
PowerOnResetCompletePollResponse,
KeystrokePollResponse,
poll,
poll_ack,
read_status,
read_terminal_id,
read_extended_id,
read_address_counter_hi,
read_address_counter_lo,
read_data,
read_multiple,
reset,
load_control_register,
load_secondary_control,
load_mask,
load_address_counter_hi,
load_address_counter_lo,
write_data,
clear,
search_forward,
search_backward,
insert_byte,
start_operation,
diagnostic_reset
)
from .exceptions import (
InterfaceError,
ReceiveError,
InterfaceTimeout,
ReceiveTimeout,
ProtocolError
)

19
pycoax/coax/exceptions.py Normal file
View File

@@ -0,0 +1,19 @@
"""
coax.exceptions
~~~~~~~~~~~~~~~
"""
class InterfaceError(Exception):
"""An interface error occurred."""
class ReceiveError(Exception):
"""A receive error occurred."""
class InterfaceTimeout(Exception):
"""The interface timed out."""
class ReceiveTimeout(Exception):
"""The receive operation timed out."""
class ProtocolError(Exception):
"""A protocol error occurred."""

218
pycoax/coax/interface1.py Normal file
View File

@@ -0,0 +1,218 @@
"""
coax.interface1
~~~~~~~~~~~~~~~
"""
from enum import Flag
import itertools
import struct
from sliplib import SlipWrapper, ProtocolError
from .exceptions import InterfaceError, InterfaceTimeout, ReceiveError, ReceiveTimeout
class Interface1:
"""A serial attached Arduino interface using the National Semiconductor
DP8340 and DP8341.
"""
def __init__(self, serial):
if serial is None:
raise ValueError('Serial port is required')
self.serial = serial
self.slip_serial = SlipSerial(self.serial)
def reset(self):
"""Reset the interface."""
original_serial_timeout = self.serial.timeout
self.serial.reset_input_buffer()
self._write_message(b'\x01')
self.serial.timeout = 5
try:
message = self._read_message()
finally:
self.serial.timeout = original_serial_timeout
if message[0] != 0x01:
raise _convert_error(message)
if len(message) != 4:
raise InterfaceError('Invalid reset response')
(major, minor, patch) = struct.unpack('BBB', message[1:])
return '{}.{}.{}'.format(major, minor, patch)
def execute(self, command_word, data=None, response_length=1, timeout=None):
"""Executes a command.
:param command_word: the command to execute
:param data: optional bytearray containing command data
:param response_length: the expected response length
:param timeout: optional timeout in seconds
"""
timeout_milliseconds = 0
if timeout:
if self.serial.timeout and timeout > self.serial.timeout:
raise ValueError('Timeout cannot be greater than serial timeout')
timeout_milliseconds = int(timeout * 1000)
message = struct.pack(">BHHH", 0x02, command_word, response_length,
timeout_milliseconds)
if data is not None:
message += data
self._write_message(message)
message = self._read_message()
if message[0] != 0x01:
raise _convert_error(message)
response_bytes = message[1:]
response_words = [(hi << 8) | lo for (lo, hi) in zip(response_bytes[::2],
response_bytes[1::2])]
# Handle any receiver (DP8341) errors that are included in the response words.
error_words = [word for word in response_words if (word & 0x8000) == 0x8000]
if error_words:
raise _convert_receiver_errors(error_words)
return response_words
def offload_load_address_counter(self, address):
"""Executes a combined LO and HI address counter load.
:param address: the address
"""
parameters = struct.pack(">H", address)
self._execute_offload(0x01, parameters)
def offload_write(self, data, address=None, restore_original_address=False, repeat=0):
"""Executes a complex write operation.
:param data: the data
:param address: optional address to load before WRITE_DATA command
:param restore_original_address: restore the original data after write
:param repeat: repeat the data
"""
parameters = struct.pack(">HBH", 0xffff if address is None else address,
0x01 if restore_original_address else 0x00,
repeat) + data
self._execute_offload(0x02, parameters)
def _execute_offload(self, command, parameters=None):
"""Executes an offloaded command."""
message = struct.pack("BB", 0x03, command)
if parameters:
message += parameters
self._write_message(message)
message = self._read_message()
if message[0] != 0x01:
raise _convert_error(message)
def _read_message(self):
try:
message = self.slip_serial.recv_msg()
except ProtocolError:
raise InterfaceError('SLIP protocol error')
if len(message) < 4:
raise InterfaceError('Invalid response message')
(length,) = struct.unpack(">H", message[:2])
if length != len(message) - 4:
raise InterfaceError('Response message length mismatch')
if length < 1:
raise InterfaceError('Empty response message')
return message[2:-2]
def _write_message(self, message):
self.slip_serial.send_msg(struct.pack(">H", len(message)) + message + struct.pack(">H", 0))
ERROR_MAP = {
1: InterfaceError('Invalid request message'),
2: InterfaceError('Unknown command'),
3: InterfaceError('Unknown offload command'),
101: InterfaceError('Receiver active'),
102: ReceiveTimeout(),
103: ReceiveError('Receiver buffer overflow')
}
def _convert_error(message):
if message[0] != 0x02:
return InterfaceError('Invalid response')
if len(message) < 2:
return InterfaceError('Invalid error response')
if message[1] in ERROR_MAP:
return ERROR_MAP[message[1]]
return InterfaceError('Unknown error')
class ReceiverErrorCode(Flag):
"""Receiver (DP8341) error code."""
DATA_OVERFLOW = 0x01
PARITY = 0x02
TRANSMIT_CHECK_CONDITIONS = 0x04
INVALID_ENDING_SEQUENCE = 0x08
MID_BID_TRANSITION = 0x10
STARTING_SEQUENCE = 0x20
RECEIVER_DISABLED = 0x40
def _parse_receiver_error(word):
return [code for code in ReceiverErrorCode if code & ReceiverErrorCode(word & 0x7f)]
def _convert_receiver_errors(words):
codes = set(itertools.chain.from_iterable([_parse_receiver_error(word) for word
in words]))
message = 'Receiver ' + ', '.join([code.name for code in codes]) + ' error'
raise ReceiveError(message)
class SlipSerial(SlipWrapper):
"""sliplib wrapper for pySerial."""
def send_bytes(self, packet):
"""Sends a packet over the serial port."""
self.stream.write(packet)
self.stream.flush()
def recv_bytes(self):
"""Receive data from the serial port."""
if self.stream.closed:
return b''
count = self.stream.in_waiting
if count:
return self.stream.read(count)
byte = self.stream.read(1)
if byte == b'':
raise InterfaceTimeout()
return byte

26
pycoax/coax/parity.py Normal file
View File

@@ -0,0 +1,26 @@
"""
coax.parity
~~~~~~~~~~~
Single byte parity computation
"""
# From http://p-nand-q.com/python/algorithms/math/bit-parity.html
def _parallel_swar(i):
i = i - ((i >> 1) & 0x55555555)
i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
i = (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24
return int(i % 2)
_PARITY_LOOKUP = [_parallel_swar(i) for i in range(256)]
def even_parity(byte):
"""Compute even parity"""
if byte < 0 or byte > 255:
raise ValueError('Input must be between 0 and 255')
return _PARITY_LOOKUP[byte]
def odd_parity(byte):
"""Compute odd parity"""
return int(not even_parity(byte))

238
pycoax/coax/protocol.py Normal file
View File

@@ -0,0 +1,238 @@
"""
coax.protocol
~~~~~~~~~~~~~
"""
from enum import Enum
from .exceptions import ProtocolError
from .parity import odd_parity
class Command(Enum):
"""Terminal command."""
# Read Commands
POLL = 0x01
POLL_ACK = 0x11
READ_STATUS = 0x0d
READ_TERMINAL_ID = 0x09
READ_EXTENDED_ID = 0x07
READ_ADDRESS_COUNTER_HI = 0x05
READ_ADDRESS_COUNTER_LO = 0x15
READ_DATA = 0x03
READ_MULTIPLE = 0x0b
# Write Commands
RESET = 0x02
LOAD_CONTROL_REGISTER = 0x0a
LOAD_SECONDARY_CONTROL = 0x1a
LOAD_MASK = 0x16
LOAD_ADDRESS_COUNTER_HI = 0x04
LOAD_ADDRESS_COUNTER_LO = 0x14
WRITE_DATA = 0x0c
CLEAR = 0x06
SEARCH_FORWARD = 0x10
SEARCH_BACKWARD = 0x12
INSERT_BYTE = 0x0e
START_OPERATION = 0x08
DIAGNOSTIC_RESET = 0x1c
class PollResponse:
"""Terminal POLL response."""
@staticmethod
def is_power_on_reset_complete(value):
"""Is the response word a power on reset complete response?"""
return value == 0xa
@staticmethod
def is_keystroke(value):
"""Is the response word a keystroke response?"""
return ((value & 0x2) == 0x2) and ((value & 0x1) == 0)
def __init__(self, value):
self.value = value
class PowerOnResetCompletePollResponse(PollResponse):
"""Terminal power-on-reset complete poll response."""
def __init__(self, value):
if not PollResponse.is_power_on_reset_complete(value):
raise ValueError('Invalid POR poll response')
super().__init__(value)
class KeystrokePollResponse(PollResponse):
"""Terminal keystroke poll response."""
def __init__(self, value):
if not PollResponse.is_keystroke(value):
raise ValueError('Invalid keystroke poll response')
super().__init__(value)
self.scan_code = (value >> 2) & 0xff
class TerminalId:
"""Terminal model and keyboard."""
def __init__(self, value):
if (value & 0x1) != 0:
raise ValueError('Invalid terminal identifier')
self.value = value
self.model = (value & 0x0e) >> 1
self.keyboard = (value & 0xf0) >> 4
def poll(interface, **kwargs):
"""Execute a POLL command."""
command_word = _pack_command_word(Command.POLL)
response = interface.execute(command_word, **kwargs)
if len(response) != 1:
raise ProtocolError('Expected 1 word POLL response')
word = response[0]
if word == 0:
return None
if PollResponse.is_power_on_reset_complete(word):
return PowerOnResetCompletePollResponse(word)
if PollResponse.is_keystroke(word):
return KeystrokePollResponse(word)
return PollResponse(word)
def poll_ack(interface, **kwargs):
"""Execute a POLL_ACK command."""
_execute_write_command(interface, Command.POLL_ACK, **kwargs)
def read_status(interface):
"""Execute a READ_STATUS command."""
raise NotImplementedError
def read_terminal_id(interface, **kwargs):
"""Execute a READ_TERMINAL_ID command."""
response = _execute_read_command(interface, Command.READ_TERMINAL_ID, **kwargs)
return TerminalId(response[0])
def read_extended_id(interface, **kwargs):
"""Execute a READ_EXTENDED_ID command."""
return _execute_read_command(interface, Command.READ_EXTENDED_ID, 4, **kwargs)
def read_address_counter_hi(interface, **kwargs):
"""Execute a READ_ADDRESS_COUNTER_HI command."""
return _execute_read_command(interface, Command.READ_ADDRESS_COUNTER_HI, **kwargs)[0]
def read_address_counter_lo(interface, **kwargs):
"""Execute a READ_ADDRESS_COUTER_LO command."""
return _execute_read_command(interface, Command.READ_ADDRESS_COUNTER_LO, **kwargs)[0]
def read_data(interface):
"""Execute a READ_DATA command."""
raise NotImplementedError
def read_multiple(interface):
"""Execute a READ_MULTIPLE command."""
raise NotImplementedError
def reset(interface):
"""Execute a RESET command."""
raise NotImplementedError
def load_control_register(interface):
"""Execute a LOAD_CONTROL_REGISTER command."""
raise NotImplementedError
def load_secondary_control(interface):
"""Execute a LOAD_SECONDARY_CONTROL command."""
raise NotImplementedError
def load_mask(interface):
"""Execute a LOAD_MASK command."""
raise NotImplementedError
def load_address_counter_hi(interface, address, **kwargs):
"""Execute a LOAD_ADDRESS_COUNTER_HI command."""
_execute_write_command(interface, Command.LOAD_ADDRESS_COUNTER_HI, bytes([address]), **kwargs)
def load_address_counter_lo(interface, address, **kwargs):
"""Execute a LOAD_ADDRESS_COUNTER_LO command."""
_execute_write_command(interface, Command.LOAD_ADDRESS_COUNTER_LO, bytes([address]), **kwargs)
def write_data(interface, data, **kwargs):
"""Execute a WRITE_DATA command."""
_execute_write_command(interface, Command.WRITE_DATA, data, **kwargs)
def clear(interface):
"""Execute a CLEAR command."""
raise NotImplementedError
def search_forward(interface):
"""Execute a SEARCH_FORWARD command."""
raise NotImplementedError
def search_backward(interface):
"""Execute a SEARCH_BACKWARD command."""
raise NotImplementedError
def insert_byte(interface):
"""Execute a INSERT_BYTE command."""
raise NotImplementedError
def start_operation(interface):
"""Execute a START_OPERATION command."""
raise NotImplementedError
def diagnostic_reset(interface):
"""Execute a DIAGNOSTIC_RESET command."""
raise NotImplementedError
def _execute_read_command(interface, command, response_length=1):
"""Execute a standard read command."""
command_word = _pack_command_word(command)
response_words = interface.execute(command_word, response_length=response_length)
if len(response_words) != response_length:
raise ProtocolError(f'Expected {response_length} word {command.name} response')
return _unpack_data_words(response_words)
def _execute_write_command(interface, command, data=None):
"""Execute a standard write command."""
command_word = _pack_command_word(command)
response_words = interface.execute(command_word, data)
if len(response_words) != 1:
raise ProtocolError(f'Expected 1 word {command.name} response')
if response_words[0] != 0:
raise ProtocolError('Expected TR/TA response')
def _pack_command_word(command, address=0):
"""Pack a command and address into a 10-bit command word for the interface."""
return (address << 7) | (command.value << 2) | 0x1
def _unpack_data_words(words):
"""Unpack the data bytes from 10-bit data words, performs parity checking."""
return bytes([_unpack_data_word(word) for word in words])
def _unpack_data_word(word):
"""Unpack the data byte from a 10-bit data word, performs parity checking."""
if not (word & 0x1) == 0x0:
raise ProtocolError('Word does not have data bit set')
byte = (word >> 2) & 0xff
parity = (word >> 1) & 0x1
if not odd_parity(byte) == parity:
raise ProtocolError('Parity error')
return byte

24
pycoax/examples/01_reset.py Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python
import sys
import time
from serial import Serial
sys.path.append('..')
from coax import Interface1, poll, poll_ack
print('Opening serial port...')
with Serial('/dev/ttyUSB0', 115200) as serial:
print('Sleeping to allow interface time to wake up...')
time.sleep(3)
interface = Interface1(serial)
print('Resetting interface...')
version = interface.reset()
print(f'Firmware version is {version}')

35
pycoax/examples/02_poll.py Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env python
import sys
import time
from serial import Serial
sys.path.append('..')
from coax import Interface1, poll, poll_ack
print('Opening serial port...')
with Serial('/dev/ttyUSB0', 115200) as serial:
print('Sleeping to allow interface time to wake up...')
time.sleep(3)
interface = Interface1(serial)
print('Resetting interface...')
version = interface.reset()
print(f'Firmware version is {version}')
print('POLL...')
poll_response = poll(interface, timeout=5)
print(poll_response)
if poll_response:
print('POLL_ACK...')
poll_ack(interface)

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python
import sys
import time
from serial import Serial
sys.path.append('..')
from coax import Interface1, read_terminal_id
print('Opening serial port...')
with Serial('/dev/ttyUSB0', 115200) as serial:
print('Sleeping to allow interface time to wake up...')
time.sleep(3)
interface = Interface1(serial)
print('Resetting interface...')
version = interface.reset()
print(f'Firmware version is {version}')
print('READ_TERMINAL_ID...')
terminal_id = read_terminal_id(interface)
print(terminal_id)

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env python
import sys
import time
from serial import Serial
sys.path.append('..')
from coax import Interface1, read_address_counter_hi, read_address_counter_lo, load_address_counter_hi, load_address_counter_lo, write_data
print('Opening serial port...')
with Serial('/dev/ttyUSB0', 115200) as serial:
print('Sleeping to allow interface time to wake up...')
time.sleep(3)
interface = Interface1(serial)
print('Resetting interface...')
version = interface.reset()
print(f'Firmware version is {version}')
print('LOAD_ADDRESS_COUNTER_HI...')
load_address_counter_hi(interface, 0)
print('LOAD_ADDRESS_COUNTER_LO...')
load_address_counter_lo(interface, 80)
print('WRITE_DATA...')
write_data(interface, bytes.fromhex('a7 84 8b 8b 8e 33 00 96 8e 91 8b 83 19'))
print('READ_ADDRESS_COUNTER_HI...')
hi = read_address_counter_hi(interface)
print('READ_ADDRESS_COUNTER_LO...')
lo = read_address_counter_lo(interface)
print(f'hi = {hi:02x}, lo = {lo:02x}')

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env python
import sys
import time
from serial import Serial
sys.path.append('..')
from coax import Interface1
print('Opening serial port...')
with Serial('/dev/ttyUSB0', 115200) as serial:
print('Sleeping to allow interface time to wake up...')
time.sleep(3)
interface = Interface1(serial)
print('Resetting interface...')
version = interface.reset()
print(f'Firmware version is {version}')
for n in range(10):
print(f'Writing line {n + 1}...')
address = ((7 + n) * 80) + 80
interface.offload_write(b'\x80', address=address, repeat=n)

2
pycoax/requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
pyserial==3.4
sliplib==0.3.0

3
pycoax/run_unit_tests.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
python -m unittest discover tests

35
pycoax/setup.py Normal file
View File

@@ -0,0 +1,35 @@
import os
from setuptools import setup
ABOUT = {}
with open(os.path.join(os.path.dirname(__file__), "coax", "__about__.py")) as file:
exec(file.read(), ABOUT)
LONG_DESCRIPTION = """# pycoax
Python IBM 3270 coaxial interface library.
See [GitHub](https://github.com/lowobservable/coax-interface#readme) for more information.
"""
setup(
name='pycoax',
version=ABOUT['__version__'],
description='IBM 3270 coaxial interface',
url='https://github.com/lowobservable/coax-interface',
author='Andrew Kay',
author_email='projects@ajk.me',
packages=['coax'],
install_requires=['pyserial==3.4', 'sliplib==0.3.0'],
long_description=LONG_DESCRIPTION,
long_description_content_type='text/markdown',
classifiers=[
'Development Status :: 3 - Alpha',
'License :: OSI Approved :: ISC License (ISCL)',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Topic :: Communications',
'Topic :: Terminals'
]
)

0
pycoax/tests/__init__.py Normal file
View File

4
pycoax/tests/context.py Normal file
View File

@@ -0,0 +1,4 @@
import sys
import os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

View File

@@ -0,0 +1,264 @@
import unittest
from unittest.mock import Mock
import sliplib
import context
from coax import Interface1, InterfaceError, ReceiveError, ReceiveTimeout
class Interface1ResetTestCase(unittest.TestCase):
def setUp(self):
self.serial = Mock()
self.serial.timeout = None
self.interface = Interface1(self.serial)
self.interface._write_message = Mock()
self.interface._read_message = Mock(return_value=bytes.fromhex('01 01 02 03'))
def test_message_is_sent(self):
# Act
self.interface.reset()
# Assert
self.interface._write_message.assert_called_with(bytes.fromhex('01'))
def test_version_is_formatted_correctly(self):
self.assertEqual(self.interface.reset(), '1.2.3')
def test_timeout_is_restored_after_reset(self):
# Arrange
self.serial.timeout = 123
# Act
self.interface.reset()
# Assert
self.assertEqual(self.serial.timeout, 123)
def test_invalid_message_length_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('01 01'))
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Invalid reset response'):
self.interface.reset()
def test_error_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('02 01'))
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Invalid request message'):
self.interface.reset()
class Interface1ExecuteTestCase(unittest.TestCase):
def setUp(self):
self.serial = Mock()
self.serial.timeout = None
self.interface = Interface1(self.serial)
self.interface._write_message = Mock()
self.interface._read_message = Mock(return_value=bytes.fromhex('01 00'))
def test_message_is_sent_without_data(self):
# Act
self.interface.execute(0b0000001001)
# Assert
self.interface._write_message.assert_called_with(bytes.fromhex('02 00 09 00 01 00 00'))
def test_message_is_sent_with_data(self):
# Act
self.interface.execute(0b0000110001, data=bytes.fromhex('de ad be ef'))
# Assert
self.interface._write_message.assert_called_with(bytes.fromhex('02 00 31 00 01 00 00 de ad be ef'))
def test_message_is_sent_with_response_length(self):
# Act
self.interface.execute(0b0000011101, response_length=4)
# Assert
self.interface._write_message.assert_called_with(bytes.fromhex('02 00 1d 00 04 00 00'))
def test_timeout_cannot_exceed_serial_timeout(self):
# Arrange
self.serial.timeout = 2.0
# Act and assert
with self.assertRaisesRegex(ValueError, 'Timeout cannot be greater than serial timeout'):
self.interface.execute(0b0000000101, timeout=3)
def test_message_is_sent_with_timeout(self):
# Act
self.interface.execute(0b0000000101, timeout=3)
# Assert
self.interface._write_message.assert_called_with(bytes.fromhex('02 00 05 00 01 0b b8'))
# TODO... interface timeout...
def test_receive_timeout_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('02 66'))
# Act and assert
with self.assertRaises(ReceiveTimeout):
self.interface.execute(0b0000000101)
def test_receive_error_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('02 67'))
# Act and assert
with self.assertRaisesRegex(ReceiveError, 'Receiver buffer overflow'):
self.interface.execute(0b0000000101)
def test_interface_error_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('03'))
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Invalid response'):
self.interface.execute(0b0000000101)
def test_response_words_are_unpacked(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('01 01 02 03 04'))
# Act
response_words = self.interface.execute(0b0000011101, response_length=4)
# Assert
self.assertEqual(response_words, [0x0201, 0x0403])
def test_receiver_error_is_handled_correctly(self):
# Arrange
self.interface._read_message = Mock(return_value=bytes.fromhex('01 a0 80'))
# Act and assert
with self.assertRaisesRegex(ReceiveError, 'Receiver STARTING_SEQUENCE error'):
self.interface.execute(0b0000011101, response_length=4)
class Interface1OffloadLoadAddressCounterTestCase(unittest.TestCase):
def setUp(self):
self.serial = Mock()
self.interface = Interface1(self.serial)
self.interface._execute_offload = Mock()
def test(self):
# Act
self.interface.offload_load_address_counter(960)
# Assert
self.interface._execute_offload.assert_called_with(0x01, bytes.fromhex('03 c0'))
class Interface1OffloadWriteTestCase(unittest.TestCase):
def setUp(self):
self.serial = Mock()
self.interface = Interface1(self.serial)
self.interface._execute_offload = Mock()
def test_message_is_sent_with_data(self):
# Act
self.interface.offload_write(bytes.fromhex('de ad be ef'))
# Assert
self.interface._execute_offload.assert_called_with(0x02, bytes.fromhex('ff ff 00 00 00 de ad be ef'))
def test_message_is_sent_with_address(self):
# Act
self.interface.offload_write(bytes.fromhex('de ad be ef'), address=960)
# Assert
self.interface._execute_offload.assert_called_with(0x02, bytes.fromhex('03 c0 00 00 00 de ad be ef'))
def test_message_is_sent_with_restore_original_address(self):
# Act
self.interface.offload_write(bytes.fromhex('de ad be ef'), restore_original_address=True)
# Assert
self.interface._execute_offload.assert_called_with(0x02, bytes.fromhex('ff ff 01 00 00 de ad be ef'))
def test_message_is_sent_with_repeat(self):
# Act
self.interface.offload_write(bytes.fromhex('de ad be ef'), repeat=1)
# Assert
self.interface._execute_offload.assert_called_with(0x02, bytes.fromhex('ff ff 00 00 01 de ad be ef'))
class Interface1ReadMessageTestCase(unittest.TestCase):
def setUp(self):
self.serial = Mock()
self.interface = Interface1(self.serial)
self.interface.slip_serial = Mock()
def test(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(return_value=bytes.fromhex('00 04 01 02 03 04 00 00'))
# Act
message = self.interface._read_message()
# Assert
self.assertEqual(message, bytes.fromhex('01 02 03 04'))
def test_protocol_error_is_handled_correctly(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(side_effect=sliplib.ProtocolError)
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'SLIP protocol error'):
self.interface._read_message()
def test_invalid_message_length_is_handled_correctly(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(return_value=bytes.fromhex('00'))
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Invalid response message'):
self.interface._read_message()
def test_message_length_mismatch_is_handled_correctly(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(return_value=bytes.fromhex('00 05 01 02 03 04 00 00'))
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Response message length mismatch'):
self.interface._read_message()
def test_empty_message_is_handled_correctly(self):
# Arrange
self.interface.slip_serial.recv_msg = Mock(return_value=bytes.fromhex('00 00 00 00'))
# Act and assert
with self.assertRaisesRegex(InterfaceError, 'Empty response message'):
self.interface._read_message()
class Interface1WriteMessageTestCase(unittest.TestCase):
def setUp(self):
self.serial = Mock()
self.interface = Interface1(self.serial)
self.interface.slip_serial = Mock()
def test(self):
# Act
self.interface._write_message(bytes.fromhex('01 02 03 04'))
# Assert
self.interface.slip_serial.send_msg.assert_called_with(bytes.fromhex('00 04 01 02 03 04 00 00'))
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,34 @@
import unittest
import context
from coax.parity import even_parity, odd_parity
class EvenParityTestCase(unittest.TestCase):
def test_with_even_input(self):
self.assertEqual(even_parity(0b00000000), 0)
def test_with_odd_input(self):
self.assertEqual(even_parity(0b00000001), 1)
def test_with_out_of_range_input(self):
for input in [-1, 256]:
with self.subTest(input=input):
with self.assertRaises(ValueError):
even_parity(input)
class OddParityTestCase(unittest.TestCase):
def test_with_even_input(self):
self.assertEqual(odd_parity(0b00000000), 1)
def test_with_odd_input(self):
self.assertEqual(odd_parity(0b00000001), 0)
def test_with_out_of_range_input(self):
for input in [-1, 256]:
with self.subTest(input=input):
with self.assertRaises(ValueError):
odd_parity(input)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,99 @@
import unittest
from unittest.mock import Mock
import context
from coax import PollResponse, KeystrokePollResponse, ProtocolError
from coax.protocol import Command, _execute_read_command, _execute_write_command, _pack_command_word, _unpack_data_words, _unpack_data_word
class PollResponseTestCase(unittest.TestCase):
def test_is_power_on_reset_complete(self):
self.assertTrue(PollResponse.is_power_on_reset_complete(0b0000001010))
def test_is_keystroke(self):
self.assertTrue(PollResponse.is_keystroke(0b1111111110))
class KeystrokePollResponseTestCase(unittest.TestCase):
def test(self):
# Act
response = KeystrokePollResponse(0b1111111110)
# Assert
self.assertEqual(response.scan_code, 0xff)
def test_not_a_keystroke(self):
with self.assertRaisesRegex(ValueError, 'Invalid keystroke poll response'):
response = KeystrokePollResponse(0b0000001000)
class ExecuteReadCommandTestCase(unittest.TestCase):
def setUp(self):
self.interface = Mock()
def test(self):
# Arrange
self.interface.execute = Mock(return_value=[0b0000000010])
# Act and assert
self.assertEqual(_execute_read_command(self.interface, Command.READ_TERMINAL_ID), bytes.fromhex('00'))
def test_unexpected_response_length(self):
# Arrange
self.interface.execute = Mock(return_value=[])
# Act and assert
with self.assertRaisesRegex(ProtocolError, 'Expected 1 word READ_TERMINAL_ID response'):
_execute_read_command(self.interface, Command.READ_TERMINAL_ID)
class ExecuteWriteCommandTestCase(unittest.TestCase):
def setUp(self):
self.interface = Mock()
def test(self):
# Arrange
self.interface.execute = Mock(return_value=[0b0000000000])
# Act and assert
_execute_write_command(self.interface, Command.WRITE_DATA, bytes.fromhex('de ad be ef'))
def test_unexpected_response_length(self):
# Arrange
self.interface.execute = Mock(return_value=[])
# Act and assert
with self.assertRaisesRegex(ProtocolError, 'Expected 1 word WRITE_DATA response'):
_execute_write_command(self.interface, Command.WRITE_DATA, bytes.fromhex('de ad be ef'))
def test_not_tr_ta_response(self):
# Arrange
self.interface.execute = Mock(return_value=[0b0000000010])
# Act and assert
with self.assertRaisesRegex(ProtocolError, 'Expected TR/TA response'):
_execute_write_command(self.interface, Command.WRITE_DATA, bytes.fromhex('de ad be ef'))
class PackCommandWordTestCase(unittest.TestCase):
def test_without_address(self):
self.assertEqual(_pack_command_word(Command.POLL_ACK), 0b001000101)
def test_with_address(self):
self.assertEqual(_pack_command_word(Command.POLL_ACK, address=3), 0b111000101)
class UnpackDataWordsTestCase(unittest.TestCase):
def test(self):
self.assertEqual(_unpack_data_words([0b0000000010, 0b1111111110]), bytes.fromhex('00 ff'))
class UnpackDataWordTestCase(unittest.TestCase):
def test(self):
self.assertEqual(_unpack_data_word(0b0000000010), 0x00)
self.assertEqual(_unpack_data_word(0b1111111110), 0xff)
def test_data_bit_not_set_error(self):
with self.assertRaisesRegex(ProtocolError, 'Word does not have data bit set'):
_unpack_data_word(0b0000000011)
def test_parity_error(self):
with self.assertRaisesRegex(ProtocolError, 'Parity error'):
_unpack_data_word(0b0000000000)
if __name__ == '__main__':
unittest.main()