mirror of
https://github.com/lowobservable/coax.git
synced 2026-02-27 01:19:52 +00:00
Firmware update...
This commit is contained in:
44
interface2/firmware/include/NewCoax.h
Normal file
44
interface2/firmware/include/NewCoax.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#define ERROR_RX_RECEIVER_ACTIVE -5
|
||||
#define ERROR_RX_TIMEOUT -2
|
||||
#define ERROR_RX_OVERFLOW -3
|
||||
|
||||
class NewCoaxDataBus;
|
||||
|
||||
enum NewCoaxReceiverState { Disabled, Idle, Receiving, Received };
|
||||
|
||||
class NewCoaxReceiver
|
||||
{
|
||||
public:
|
||||
NewCoaxReceiver(NewCoaxDataBus &dataBus) : _dataBus(dataBus) { };
|
||||
|
||||
void begin();
|
||||
void enable();
|
||||
void disable();
|
||||
int receive(uint16_t *buffer, size_t bufferSize, uint16_t timeout);
|
||||
void activeInterrupt();
|
||||
void dataAvailableInterrupt();
|
||||
void errorInterrupt();
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
class NewCoaxDataBus
|
||||
{
|
||||
public:
|
||||
void setMode(int mode);
|
||||
uint16_t read();
|
||||
void write(uint16_t word);
|
||||
uint16_t encode(uint16_t word);
|
||||
uint16_t decode(uint16_t word);
|
||||
};
|
||||
242
interface2/firmware/src/NewCoax.cpp
Normal file
242
interface2/firmware/src/NewCoax.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <NewCoax.h>
|
||||
|
||||
//#define RX_ENABLE_PIN 4
|
||||
#define RX_RESET_PIN 4
|
||||
#define RX_ACTIVE_PIN 5
|
||||
#define RX_ERROR_PIN 6
|
||||
#define RX_DATA_AVAILABLE_PIN 7
|
||||
#define RX_READ_PIN 8
|
||||
|
||||
#define DATA_BUS_START_PIN 14
|
||||
#define DATA_BUS_END_PIN 23
|
||||
#define DATA_BUS_MASK 0x0fcf0000
|
||||
|
||||
static NewCoaxReceiver *receiver = NULL;
|
||||
|
||||
void rxActiveInterrupt()
|
||||
{
|
||||
if (receiver == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
receiver->activeInterrupt();
|
||||
}
|
||||
|
||||
void rxErrorInterrupt()
|
||||
{
|
||||
if (receiver == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
receiver->errorInterrupt();
|
||||
}
|
||||
|
||||
void rxDataAvailableInterrupt()
|
||||
{
|
||||
if (receiver == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
receiver->dataAvailableInterrupt();
|
||||
}
|
||||
|
||||
void NewCoaxReceiver::begin()
|
||||
{
|
||||
receiver = this;
|
||||
|
||||
//pinMode(RX_ENABLE_PIN, OUTPUT);
|
||||
pinMode(RX_RESET_PIN, OUTPUT);
|
||||
pinMode(RX_ACTIVE_PIN, INPUT);
|
||||
pinMode(RX_ERROR_PIN, INPUT);
|
||||
pinMode(RX_DATA_AVAILABLE_PIN, INPUT);
|
||||
pinMode(RX_READ_PIN, OUTPUT);
|
||||
|
||||
attachInterrupt(digitalPinToInterrupt(RX_ACTIVE_PIN), rxActiveInterrupt, RISING);
|
||||
attachInterrupt(digitalPinToInterrupt(RX_ERROR_PIN), rxErrorInterrupt, RISING);
|
||||
attachInterrupt(digitalPinToInterrupt(RX_DATA_AVAILABLE_PIN), rxDataAvailableInterrupt, RISING);
|
||||
}
|
||||
|
||||
void NewCoaxReceiver::enable()
|
||||
{
|
||||
_dataBus.setMode(INPUT);
|
||||
|
||||
_state = Idle;
|
||||
|
||||
//digitalWrite(RX_ENABLE_PIN, HIGH);
|
||||
}
|
||||
|
||||
void NewCoaxReceiver::disable()
|
||||
{
|
||||
//digitalWrite(RX_ENABLE_PIN, LOW);
|
||||
|
||||
_state = Disabled;
|
||||
}
|
||||
|
||||
int NewCoaxReceiver::receive(uint16_t *buffer, size_t bufferSize, uint16_t timeout)
|
||||
{
|
||||
if (_state != Disabled) {
|
||||
return ERROR_RX_RECEIVER_ACTIVE;
|
||||
}
|
||||
|
||||
_error = 0;
|
||||
_buffer = buffer;
|
||||
_bufferSize = bufferSize;
|
||||
_bufferCount = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Unscramble the data.
|
||||
for (int index = 0; index < count; index++) {
|
||||
buffer[index] = _dataBus.decode(buffer[index]);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void NewCoaxReceiver::activeInterrupt()
|
||||
{
|
||||
if (_state != Idle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Flush any old data.
|
||||
if (digitalRead(RX_DATA_AVAILABLE_PIN)) {
|
||||
read();
|
||||
}
|
||||
|
||||
_bufferCount = 0;
|
||||
_state = Receiving;
|
||||
}
|
||||
|
||||
void NewCoaxReceiver::dataAvailableInterrupt()
|
||||
{
|
||||
if (_state != Receiving) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t word = read();
|
||||
|
||||
if (_bufferCount < _bufferSize) {
|
||||
_buffer[_bufferCount++] = word;
|
||||
} else {
|
||||
_bufferCount = _bufferSize + 1;
|
||||
}
|
||||
|
||||
// TODO: this is wrong... but it allows things to settle!
|
||||
delayMicroseconds(1);
|
||||
|
||||
if (!digitalRead(RX_ACTIVE_PIN) && !digitalRead(RX_DATA_AVAILABLE_PIN)) {
|
||||
_state = Received;
|
||||
}
|
||||
}
|
||||
|
||||
void NewCoaxReceiver::errorInterrupt()
|
||||
{
|
||||
_error = _dataBus.decode(read());
|
||||
|
||||
if (_state == Receiving) {
|
||||
_state = Received;
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void NewCoaxReceiver::reset()
|
||||
{
|
||||
digitalWrite(RX_RESET_PIN, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(RX_RESET_PIN, LOW);
|
||||
}
|
||||
|
||||
inline uint16_t NewCoaxReceiver::read()
|
||||
{
|
||||
digitalWrite(RX_READ_PIN, HIGH);
|
||||
|
||||
uint16_t word = _dataBus.read();
|
||||
|
||||
delayMicroseconds(1);
|
||||
|
||||
digitalWrite(RX_READ_PIN, LOW);
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
void NewCoaxDataBus::setMode(int mode)
|
||||
{
|
||||
for (int pin = DATA_BUS_START_PIN; pin <= DATA_BUS_END_PIN; pin++) {
|
||||
pinMode(pin, mode);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint16_t NewCoaxDataBus::read()
|
||||
{
|
||||
return (GPIO6_DR & DATA_BUS_MASK) >> 16;
|
||||
}
|
||||
|
||||
inline void NewCoaxDataBus::write(uint16_t word)
|
||||
{
|
||||
uint32_t bus = (word << 16) & DATA_BUS_MASK;
|
||||
|
||||
GPIO6_DR_SET = bus;
|
||||
GPIO6_DR_CLEAR = ~bus;
|
||||
}
|
||||
|
||||
inline uint16_t NewCoaxDataBus::encode(uint16_t word)
|
||||
{
|
||||
return ((word & 0x0020) >> 5)
|
||||
| ((word & 0x0010) >> 3)
|
||||
| (word & 0x0300)
|
||||
| ((word & 0x0003) << 2)
|
||||
| ((word & 0x0008) << 3)
|
||||
| ((word & 0x00c0) << 4)
|
||||
| ((word & 0x0004) << 5);
|
||||
}
|
||||
|
||||
inline uint16_t NewCoaxDataBus::decode(uint16_t word)
|
||||
{
|
||||
return ((word & 0x0080) >> 5)
|
||||
| ((word & 0x0c00) >> 4)
|
||||
| ((word & 0x0040) >> 3)
|
||||
| ((word & 0x000c) >> 2)
|
||||
| (word & 0x0300)
|
||||
| ((word & 0x0002) << 3)
|
||||
| ((word & 0x0001) << 5);
|
||||
}
|
||||
@@ -1,59 +1,26 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#define RESET_PIN 2 // FPGA #9
|
||||
#include <NewCoax.h>
|
||||
|
||||
char buffer[20 + 1];
|
||||
int bufferIndex = 0;
|
||||
NewCoaxDataBus dataBus;
|
||||
NewCoaxReceiver receiver(dataBus);
|
||||
|
||||
void doReset()
|
||||
{
|
||||
Serial.println("RESET");
|
||||
|
||||
digitalWrite(RESET_PIN, HIGH);
|
||||
digitalWrite(RESET_PIN, LOW);
|
||||
|
||||
Serial.println("OK");
|
||||
}
|
||||
uint16_t buffer[1024];
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(RESET_PIN, OUTPUT);
|
||||
|
||||
digitalWrite(RESET_PIN, LOW);
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
while (Serial.available() > 0) {
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println("OK");
|
||||
receiver.begin();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (Serial.available() > 0) {
|
||||
uint8_t byte = Serial.read();
|
||||
int count = receiver.receive(buffer, 1024, 1000);
|
||||
|
||||
if (byte == '\r') {
|
||||
buffer[bufferIndex] = 0;
|
||||
|
||||
Serial.println();
|
||||
|
||||
if (strncmp(buffer, "reset", 20) == 0) {
|
||||
doReset();
|
||||
} else {
|
||||
Serial.println("UNRECOGNIZED COMMAND");
|
||||
}
|
||||
|
||||
Serial.flush();
|
||||
|
||||
bufferIndex = 0;
|
||||
} else {
|
||||
buffer[bufferIndex++] = byte;
|
||||
}
|
||||
|
||||
Serial.write(byte);
|
||||
Serial.flush();
|
||||
}
|
||||
Serial.println(count);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user