Skip to content

Commit

Permalink
Working on parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
bdring committed Oct 3, 2023
1 parent 989cd58 commit 41dd0f0
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 3 deletions.
23 changes: 23 additions & 0 deletions FluidNC/src/Pin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
#include "Pins/GPIOPinDetail.h"
#include "Pins/VoidPinDetail.h"
#include "Pins/I2SOPinDetail.h"
#include "Pins/UARTPinDetail.h"
#include "Pins/ErrorPinDetail.h"
#include "string_util.h"
#include "Machine/MachineConfig.h" // config
#include <string_view>

Pins::PinDetail* Pin::undefinedPin = new Pins::VoidPinDetail();
Pins::PinDetail* Pin::errorPin = new Pins::ErrorPinDetail("unknown");
Expand Down Expand Up @@ -73,8 +76,28 @@ const char* Pin::parse(std::string_view pin_str, Pins::PinDetail*& pinImplementa
pinImplementation = new Pins::GPIOPinDetail(static_cast<pinnum_t>(pin_number), parser);
}
if (string_util::equal_ignore_case(prefix, "i2so")) {
if (config->_i2so == nullptr) {
return "i2so: section must be defined before using i2so pins";
}
pinImplementation = new Pins::I2SOPinDetail(static_cast<pinnum_t>(pin_number), parser);
}

if (prefix.length() == 13) {
if (prefix.substr(0, 12) == "uart_channel") {
log_info("More:" << prefix[12]);
if (prefix[12] >= '0' && prefix[12] <= '2') { // TODO use MAX_N_UARTS
// check to see if the channel exits
auto deviceId = prefix[12] - '0';
if (config->_uart_channels[deviceId] == nullptr) {
return " uart channel number not found";
}
pinImplementation = new Pins::UARTIODetail(deviceId, pinnum_t(pin_number), parser);
} else {
return "Incorrect pin extender specification. Expected 'pinext[0-2].[port number]'.";
}
}
}

if (string_util::equal_ignore_case(prefix, "no_pin")) {
pinImplementation = undefinedPin;
}
Expand Down
1 change: 1 addition & 0 deletions FluidNC/src/Pins/PinCapabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace Pins {

PinCapabilities PinCapabilities::Native(1 << (__LINE__ - START_LINE));
PinCapabilities PinCapabilities::I2S(1 << (__LINE__ - START_LINE));
PinCapabilities PinCapabilities::UARTIO(1 << (__LINE__ - START_LINE));
PinCapabilities PinCapabilities::Error(1 << (__LINE__ - START_LINE));
PinCapabilities PinCapabilities::Void(1 << (__LINE__ - START_LINE));
}
3 changes: 2 additions & 1 deletion FluidNC/src/Pins/PinCapabilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Pins {
friend class PinAttributes; // Wants access to _value for validation

public:
PinCapabilities(const PinCapabilities&) = default;
PinCapabilities(const PinCapabilities&) = default;
PinCapabilities& operator=(const PinCapabilities&) = default;

// All the capabilities we use and test:
Expand All @@ -44,6 +44,7 @@ namespace Pins {
// can compare classes of pins along with their properties by just looking at the capabilities.
static PinCapabilities Native;
static PinCapabilities I2S;
static PinCapabilities UARTIO;
static PinCapabilities Error;
static PinCapabilities Void;

Expand Down
107 changes: 107 additions & 0 deletions FluidNC/src/Pins/UARTPinDetail.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) 2023 Bart Dring
// Use of this source code is governed by a GPLv3 license that can be found in the LICENSE file.

#ifdef ESP32
# include "UARTPinDetail.h"
# include "PinDetail.h"

# include "../I2SOut.h"
# include "../Assert.h"

namespace Pins {
std::vector<bool> UARTIODetail::_claimed(nPins, false);

UARTIODetail::UARTIODetail(int deviceId, pinnum_t index, const PinOptionsParser& options) :
PinDetail(index), _capabilities(PinCapabilities::Output | PinCapabilities::UARTIO), _attributes(Pins::PinAttributes::Undefined),
_readWriteMask(0) {
Assert(index < nPins, "Pin number is greater than max %d", nPins - 1);
Assert(!_claimed[index], "Pin is already used.");

// User defined pin capabilities
for (auto opt : options) {
if (opt.is("pu")) {
} else if (opt.is("pd")) {
} else if (opt.is("low")) {
_attributes = _attributes | PinAttributes::ActiveLow;
} else if (opt.is("high")) {
// Default: Active HIGH.
} else {
Assert(false, "Bad UARTPin option passed to pin %d: %s", int(index), opt());
}
}

_device_id = deviceId;

//log_info("created uart pin:" << index);
_claimed[index] = true;

// readWriteMask is xor'ed with the value to invert it if active low
_readWriteMask = int(_attributes.has(PinAttributes::ActiveLow));
}
// The write will not happen immediately; the data is queued for
// delivery to the serial shift register chain via DMA and a FIFO

PinCapabilities UARTIODetail::capabilities() const {
return PinCapabilities::Output | PinCapabilities::UARTIO;
}

void IRAM_ATTR UARTIODetail::write(int high) {
if (high != _lastWrittenValue) {
_lastWrittenValue = high;
if (!_attributes.has(PinAttributes::Output)) {
log_error(toString());
}
Assert(_attributes.has(PinAttributes::Output), "Pin %s cannot be written", toString().c_str());
int value = _readWriteMask ^ high;
log_info("Set uart pin:" << high);
}
}

int UARTIODetail::read() {
return 0;
}

void UARTIODetail::setAttr(PinAttributes value) {
// These two assertions will fail if we do them for index 1/3 (Serial uart). This is because
// they are initialized by HardwareSerial well before we start our main operations. Best to
// just ignore them for now, and figure this out later. TODO FIXME!

// Check the attributes first:
Assert(value.validateWith(this->_capabilities) || _index == 1 || _index == 3,
"The requested attributes don't match the capabilities for %s",
toString().c_str());
Assert(!_attributes.conflictsWith(value) || _index == 1 || _index == 3,
"The requested attributes on %s conflict with previous settings",
toString().c_str());

_attributes = _attributes | value;

// If the pin is ActiveLow, we should take that into account here:
if (value.has(PinAttributes::Output)) {
//gpio_write(_index, int(value.has(PinAttributes::InitialOn)) ^ _readWriteMask);
}
}

PinAttributes UARTIODetail::getAttr() const {
return _attributes;
}

std::string UARTIODetail::toString() {
std::string s("uart_channel");
s += std::to_string(_device_id);
s += ".";
s += std::to_string(_index);
if (_attributes.has(PinAttributes::ActiveLow)) {
s += ":low";
}
if (_attributes.has(PinAttributes::PullUp)) {
s += ":pu";
}
if (_attributes.has(PinAttributes::PullDown)) {
s += ":pd";
}
return s;
}
}

#endif
38 changes: 38 additions & 0 deletions FluidNC/src/Pins/UARTPinDetail.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2023 B. Dring
// Use of this source code is governed by a GPLv3 license that can be found in the LICENSE file.

#pragma once
#ifdef ESP32

# include "PinDetail.h"

namespace Pins {
class UARTIODetail : public PinDetail {
PinCapabilities _capabilities;
PinAttributes _attributes;
int _readWriteMask;

int _device_id;

static const int nPins = 255;
static std::vector<bool> _claimed;

bool _lastWrittenValue = false;

public:
UARTIODetail(int deviceId, pinnum_t index, const PinOptionsParser& options);

// I/O:
PinCapabilities capabilities() const override;
void write(int high) override;
int read() override;
void setAttr(PinAttributes value) override;
PinAttributes getAttr() const override;

std::string toString() override;

~UARTIODetail() override { _claimed[_index] = false; }
};
}

#endif
1 change: 1 addition & 0 deletions FluidNC/src/UartChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ void UartChannel::init() {
void UartChannel::init(Uart* uart) {
_uart = uart;
allChannels.registration(this);
log_info("uart_channel" << _uart_num << " created");
}

size_t UartChannel::write(uint8_t c) {
Expand Down
8 changes: 6 additions & 2 deletions FluidNC/src/UartChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class UartChannel : public Channel, public Configuration::Configurable {
Lineedit* _lineedit;
Uart* _uart;

int _uart_num = 0;
int _uart_num = 0;
bool _has_pins = false; // the device is a pin extender

public:
UartChannel(bool addCR = false);
Expand All @@ -39,7 +40,10 @@ class UartChannel : public Channel, public Configuration::Configurable {
Channel* pollLine(char* line) override;

// Configuration methods
void group(Configuration::HandlerBase& handler) override { handler.item("uart_num", _uart_num); }
void group(Configuration::HandlerBase& handler) override {
handler.item("uart_num", _uart_num);
handler.item("has_pins", _has_pins);
}
};

extern UartChannel Uart0;
Expand Down

0 comments on commit 41dd0f0

Please sign in to comment.