This commit is contained in:
Andrew Kay
2020-08-25 19:31:43 -05:00
parent a137b00b0d
commit 05438f2c60
5 changed files with 92 additions and 203 deletions

View File

@@ -1,21 +0,0 @@
// Copyright (c) 2020, 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
class CoaxTransceiver {
public:
static void setup();
static int /* ssize_t */ transmitReceive(uint16_t *transmitBuffer, size_t transmitBufferCount, uint16_t *receiveBuffer, size_t receiveBufferSize, uint16_t receiveTimeout);
};

View File

@@ -14,32 +14,12 @@
#pragma once
#define ERROR_TX_RECEIVER_ACTIVE -1
#define ERROR_RX_RECEIVER_ACTIVE -5
#define ERROR_RX_TIMEOUT -2
#define ERROR_RX_OVERFLOW -3
class NewCoaxReceiver;
class NewCoaxDataBus;
class NewCoaxTransmitter
{
public:
NewCoaxTransmitter(NewCoaxDataBus &dataBus, NewCoaxReceiver &receiver) :
_dataBus(dataBus), _receiver(receiver) { };
void begin();
int transmit(uint16_t *buffer, size_t bufferCount);
private:
NewCoaxDataBus &_dataBus;
NewCoaxReceiver &_receiver;
void reset();
void write(uint16_t word);
};
enum NewCoaxReceiverState { Disabled, Idle, Receiving, Received };
class NewCoaxReceiver
@@ -50,7 +30,7 @@ public:
void begin();
void enable();
void disable();
int receive(uint16_t *buffer, size_t bufferSize, uint16_t timeout);
void reset();
void activeInterrupt();
void dataAvailableInterrupt();
void errorInterrupt();
@@ -58,12 +38,7 @@ public:
private:
NewCoaxDataBus &_dataBus;
volatile NewCoaxReceiverState _state = Disabled;
volatile uint16_t _error;
volatile uint16_t *_buffer;
volatile size_t _bufferSize;
volatile int _bufferCount;
void reset();
uint16_t read();
};

View File

@@ -1,41 +0,0 @@
// Copyright (c) 2020, 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 "NewCoax.h"
#include "CoaxTransceiver.h"
NewCoaxDataBus dataBus;
NewCoaxReceiver receiver(dataBus);
NewCoaxTransmitter transmitter(dataBus, receiver);
void CoaxTransceiver::setup()
{
dataBus.setMode(INPUT, true);
receiver.begin();
transmitter.begin();
}
int /* ssize_t */ CoaxTransceiver::transmitReceive(uint16_t *transmitBuffer, size_t transmitBufferCount, uint16_t *receiveBuffer, size_t receiveBufferSize, uint16_t receiveTimeout)
{
int returnValue = transmitter.transmit(transmitBuffer, transmitBufferCount);
if (returnValue < 0) {
return returnValue;
}
return receiver.receive(receiveBuffer, receiveBufferSize, receiveTimeout);
}

View File

@@ -61,63 +61,6 @@ void rxDataAvailableInterrupt()
receiver->dataAvailableInterrupt();
}
void NewCoaxTransmitter::begin()
{
pinMode(RESET_PIN, OUTPUT);
pinMode(TX_ACTIVE_PIN, INPUT);
pinMode(TX_LOAD_PIN, OUTPUT);
pinMode(TX_FULL_PIN, INPUT);
}
int NewCoaxTransmitter::transmit(uint16_t *buffer, size_t bufferCount)
{
if (digitalRead(RX_ACTIVE_PIN)) {
return ERROR_TX_RECEIVER_ACTIVE;
}
_receiver.disable();
_dataBus.setMode(OUTPUT, true);
for (int index = 0; index < bufferCount; index++) {
while (digitalRead(TX_FULL_PIN)) {
// NOP
}
write(buffer[index]);
// TODO: the Teensy, too fast!
delayMicroseconds(2);
}
_dataBus.setMode(INPUT, true);
while (digitalRead(TX_ACTIVE_PIN)) {
// NOP
}
return bufferCount;
}
void NewCoaxTransmitter::reset()
{
digitalWrite(RESET_PIN, HIGH);
delayMicroseconds(1);
digitalWrite(RESET_PIN, LOW);
}
inline void NewCoaxTransmitter::write(uint16_t word)
{
digitalWrite(TX_LOAD_PIN, HIGH);
_dataBus.write(word);
delayMicroseconds(1);
digitalWrite(TX_LOAD_PIN, LOW);
}
void NewCoaxReceiver::begin()
{
receiver = this;
@@ -151,56 +94,37 @@ void NewCoaxReceiver::disable()
_state = Disabled;
}
int NewCoaxReceiver::receive(uint16_t *buffer, size_t bufferSize, uint16_t timeout)
#define FRAME_END 0xc0
#define FRAME_ESCAPE 0xdb
#define FRAME_ESCAPE_END 0xdc
#define FRAME_ESCAPE_ESCAPE 0xdd
inline void slipWrite(uint8_t value)
{
if (_state != Disabled) {
return ERROR_RX_RECEIVER_ACTIVE;
if (value == FRAME_END) {
Serial.write(FRAME_ESCAPE);
Serial.write(FRAME_ESCAPE_END);
} else if (value == FRAME_ESCAPE) {
Serial.write(FRAME_ESCAPE);
Serial.write(FRAME_ESCAPE_ESCAPE);
} else {
Serial.write(value);
}
}
_error = 0;
_buffer = buffer;
_bufferSize = bufferSize;
_bufferCount = 0;
inline void slipWrite(uint16_t value)
{
// Byte order consistent with original interface...
slipWrite((uint8_t) (value & 0xff));
slipWrite((uint8_t) ((value >> 8) & 0xff));
}
if (digitalRead(RX_DATA_AVAILABLE_PIN) || digitalRead(RX_ERROR_PIN)) {
reset();
}
enable();
if (timeout > 0) {
unsigned long startTime = millis();
while (_state == Idle) {
// https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html#unsigned
if ((millis() - startTime) > timeout) {
disable();
return ERROR_RX_TIMEOUT;
}
}
}
while (_state != Received) {
// NOP
}
// Copy the count and error then disable.
uint16_t count = _bufferCount;
uint16_t error = _error;
disable();
// Detect a receiver error.
if (error > 0) {
return (-1) * (error + 100);
}
// Detect a buffer overflow.
if (count > bufferSize) {
return ERROR_RX_OVERFLOW;
}
return count;
inline void slipWrite(uint32_t value)
{
slipWrite((uint8_t) (value & 0xff));
slipWrite((uint8_t) ((value >> 8) & 0xff));
slipWrite((uint8_t) ((value >> 16) & 0xff));
slipWrite((uint8_t) ((value >> 24) & 0xff));
}
void NewCoaxReceiver::activeInterrupt()
@@ -214,7 +138,10 @@ void NewCoaxReceiver::activeInterrupt()
read();
}
_bufferCount = 0;
Serial.write(FRAME_END);
slipWrite(millis());
_state = Receiving;
}
@@ -226,28 +153,28 @@ void NewCoaxReceiver::dataAvailableInterrupt()
uint16_t word = read();
if (_bufferCount < _bufferSize) {
_buffer[_bufferCount++] = word;
} else {
_bufferCount = _bufferSize + 1;
}
slipWrite(word);
// TODO: this is wrong... but it allows things to settle!
delayMicroseconds(1);
if (!digitalRead(RX_ACTIVE_PIN) && !digitalRead(RX_DATA_AVAILABLE_PIN)) {
_state = Received;
Serial.write(FRAME_END);
_state = Idle;
}
}
void NewCoaxReceiver::errorInterrupt()
{
_error = _dataBus.read();
if (_state == Receiving) {
_state = Received;
if (_state != Receiving) {
return;
}
uint16_t error = 0x8000 | _dataBus.read();
slipWrite(error);
reset();
}

View File

@@ -1 +0,0 @@
../../../interface1/firmware/src/main.cpp

View File

@@ -0,0 +1,50 @@
// 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 "NewCoax.h"
NewCoaxDataBus dataBus;
NewCoaxReceiver receiver(dataBus);
void setup()
{
// Configure serial port and state machine.
Serial.begin(115200);
while (Serial.available() > 0) {
Serial.read();
}
// Configure the receiver.
dataBus.setMode(INPUT, true);
receiver.begin();
}
void loop()
{
if (Serial.available() > 0) {
uint8_t byte = Serial.read();
if (byte == 'e') {
receiver.enable();
} else if (byte == 'd') {
receiver.disable();
} else if (byte == 'r') {
receiver.reset();
}
}
}