Skip to content

Commit

Permalink
Add sideband control PTY for FS and reset lines (#374)
Browse files Browse the repository at this point in the history
* Add sideband control PTY for FS and reset lines

* Add sideband test coverage for MMU2
  • Loading branch information
vintagepc committed Feb 7, 2024
1 parent faf2283 commit 6f034c9
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 38 deletions.
2 changes: 2 additions & 0 deletions parts/Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ namespace Boards
inline std::string GetSDCardFile(){return m_strSDFile.empty()?GetStorageFileName("SDcard"):m_strSDFile;}

inline void SetResetFlag(){m_bReset = true;}
inline bool GetResetFlag(){return m_bReset;}
inline void SetQuitFlag(){m_bQuit = true; m_bPaused = false;}
inline bool GetQuitFlag(){return m_bQuit;}

inline bool IsStarted(){ return m_thread!=0; }
inline bool IsStopped(){ return m_pAVR->state == cpu_Stopped;}
inline bool IsPaused(){ return m_bPaused;}

Expand Down
16 changes: 16 additions & 0 deletions parts/boards/MM_Control_01.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ namespace Boards
#endif
}

void MM_Control_01::OnAVRReset()
{
if (m_bSidebandInit)
{
std::cout << "Sideband reset complete\n";
m_USideband.BypassXON();
}
}

void MM_Control_01::SetupSideband()
{
m_USideband.Init(m_pAVR);
m_USideband.ConnectPTYOnly("/tmp/MK404-MMU-sideband");
m_bSidebandInit = true;
}

void MM_Control_01::SetupHardware()
{
DisableInterruptLevelPoll(5);
Expand Down
8 changes: 7 additions & 1 deletion parts/boards/MM_Control_01.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,18 @@ namespace Boards
void Draw(float fY);

protected:

void OnAVRReset() override;

void SetupHardware() override;

void SetupSideband();

// void CustomAVRInit() override;

// void CustomAVRDeinit() override;

uart_pty m_UART;
uart_pty m_UART, m_USideband;
HC595 m_shift;
TMC2130 m_Sel {'S'},
m_Idl {'I'},
Expand All @@ -73,5 +77,7 @@ namespace Boards
const Wirings::MM_Control_01 m_wiring = Wirings::MM_Control_01();

std::string m_strTitle = "Missing Material Unit 2";

bool m_bSidebandInit = false;
};
}; // namespace Boards
52 changes: 47 additions & 5 deletions parts/components/MMU2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "IKeyClient.h"
#include "LED.h" // for LED
#include "MM_Control_01.h" // for MM_Control_01
#include "MMUSideband.h"
#include "PinNames.h" // for Pin::FINDA_PIN
#include "TMC2130.h" // for TMC2130
#include "gsl-lite.hpp"
Expand All @@ -40,7 +41,7 @@ MMU2 *MMU2::g_pMMU = nullptr;

using Boards::MM_Control_01;

MMU2::MMU2(bool bCreate):IKeyClient(),MM_Control_01()
MMU2::MMU2(bool bCreate, bool bSetupSB):IKeyClient(),MM_Control_01(),m_bSidebandEnabled(bSetupSB)
{
if (g_pMMU)
{
Expand Down Expand Up @@ -128,18 +129,23 @@ void MMU2::SetupHardware()
m_Idl.ConnectTo(TMC2130::POSITION_OUT,GetIRQ(IDLER_OUT));
m_Extr.ConnectTo(TMC2130::POSITION_OUT,GetIRQ(PULLEY_IN));
m_shift.ConnectTo(HC595::SHIFT_OUT, GetIRQ(SHIFT_IN));

if (m_bSidebandEnabled)
{
SetupSidebandControl();
}
}


void MMU2::OnResetIn(struct avr_irq_t *irq, uint32_t value)
{
if (!value && !m_bStarted)
if (!value && !IsStarted())
{
StartAVR();
}
else if (irq->value && !value)
{
m_bReset = true;
SetResetFlag();
}
}

Expand All @@ -151,17 +157,53 @@ void MMU2::ToggleFINDA()
RaiseIRQ(FINDA_OUT,m_bFINDAManual? 1 : 0);
}

void MMU2::SetupSidebandControl()
{
MM_Control_01::SetupSideband();
RegisterNotify(SB_BYTE_IN, MAKE_C_CALLBACK(MMU2, OnSidebandByteIn), this);
ConnectTo(SB_FS, m_USideband.GetIRQ(uart_pty::BYTE_IN));
ConnectFrom(m_USideband.GetIRQ(uart_pty::BYTE_OUT), SB_BYTE_IN);
}

void MMU2::OnSidebandByteIn(struct avr_irq_t * ,uint32_t value)
{
switch (value)
{
case MMUSideband::RESET:
std::cout << "MMU Received sideband RESET signal\n";
RaiseIRQ(RESET,1);
RaiseIRQ(RESET,0);
break;
default:
std::cerr << "Unrecognized sideband control character:" << (char)value << "\n";
break;
}
}

void MMU2::OnPulleyFeedIn(struct avr_irq_t * ,uint32_t value)
{
float posOut;
std::memcpy(&posOut, &value,4);

if (m_bAutoFINDA)
{
SetPin(FINDA_PIN,posOut>33.0f);
SetPin(FINDA_PIN, posOut > FINDA_TRIGGER_DISTANCE);
// Reflect the distance out for IR sensor triggering.
RaiseIRQ(FEED_DISTANCE, value);
RaiseIRQ(FINDA_OUT,posOut>33.f);
RaiseIRQ(FINDA_OUT, posOut > FINDA_TRIGGER_DISTANCE);

if (m_bSidebandEnabled)
{
if (m_fLastPosOut < FSENSOR_TRIGGER_DISTANCE && posOut >= FSENSOR_TRIGGER_DISTANCE)
{
RaiseIRQ(SB_FS, MMUSideband::FS_AUTO_SET);
}
else if (m_fLastPosOut >= FSENSOR_TRIGGER_DISTANCE && posOut < FSENSOR_TRIGGER_DISTANCE)
{
RaiseIRQ(SB_FS, MMUSideband::FS_AUTO_CLEAR);
}
m_fLastPosOut = posOut;
}
}
else
{
Expand Down
23 changes: 17 additions & 6 deletions parts/components/MMU2.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ class MMU2: public BasePeripheral, public Boards::MM_Control_01, virtual private
public:
#define IRQPAIRS _IRQ(FEED_DISTANCE,"<mmu.feed_distance") _IRQ(RESET,"<mmu.reset") _IRQ(PULLEY_IN,"<mmu.pulley_in") \
_IRQ(SELECTOR_OUT,">sel_pos.out") _IRQ(IDLER_OUT,">idler_pos.out") _IRQ(LEDS_OUT,">leds.out") _IRQ(FINDA_OUT,">finda.out") \
_IRQ(SHIFT_IN,"<32shift.in")
_IRQ(SHIFT_IN,"<32shift.in") _IRQ(SB_FS, ">sideband_fs.out") _IRQ(SB_BYTE_IN, "sideband_byte.in")
#include "IRQHelper.h"

// Creates a new MMU2. Creates board and starts it if bCreate = true
explicit MMU2(bool bCreate = true);
explicit MMU2(bool bCreate = true, bool bSetupSideband = false);

~MMU2() override {StopAVR();}

Expand All @@ -53,7 +53,16 @@ class MMU2: public BasePeripheral, public Boards::MM_Control_01, virtual private
inline void SetFINDAState(bool bVal) {m_bFINDAManual = bVal;}
void ToggleFINDA();


protected:

static constexpr float FINDA_TRIGGER_DISTANCE = 33.f;
static constexpr float FSENSOR_TRIGGER_DISTANCE = 400.f;

#ifdef TEST_MODE
friend void Test_MMU2_internal();
#endif

enum Actions
{
// We have to extend board rather than being our own IScriptable due
Expand All @@ -71,19 +80,21 @@ class MMU2: public BasePeripheral, public Boards::MM_Control_01, virtual private

private:

void* Run();
void SetupSidebandControl();

void OnResetIn(avr_irq_t *irq, uint32_t value);

void OnPulleyFeedIn(avr_irq_t *irq, uint32_t value);

void LEDHandler(avr_irq_t *irq, uint32_t value);

void OnSidebandByteIn(avr_irq_t *irq, uint32_t value);

std::atomic_bool m_bAutoFINDA = {true};
std::atomic_bool m_bFINDAManual = {false};
std::atomic_bool m_bStarted = {false};
std::atomic_bool m_bReset ={false};
pthread_t m_tRun = 0;

bool m_bSidebandEnabled = false;
float m_fLastPosOut = 0;

static MMU2 *g_pMMU; // Needed for GL
};
84 changes: 59 additions & 25 deletions parts/components/uart_pty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ int
//#define TRACE(_w) _w
#ifndef TRACE
#define TRACE(_w)
#else
#include "sim_hex.h"
#endif

using std::cout;
Expand Down Expand Up @@ -91,7 +93,7 @@ void uart_pty::FlushData()
{
std::lock_guard<std::mutex> lock(m_lock);
while (m_bXOn && !uart_pty_fifo_isempty(&pty.out)) {
TRACE(int r = p->pty.out.read;)
TRACE(int r = pty.out.read;)
uint8_t byte = uart_pty_fifo_read(&pty.out);
TRACE(printf("uart_pty_flush_incoming send r %03d:%02x\n", r, byte);)
if (m_chrLast == '\n' && byte == '\n')
Expand Down Expand Up @@ -278,14 +280,8 @@ void* uart_pty::Run()
return nullptr;
}

void uart_pty::Init(struct avr_t * avr, char uart)
void uart_pty::InitPrivate()
{
_Init(avr,this);
uint32_t f = 0;
avr_ioctl(m_pAVR, AVR_IOCTL_UART_GET_FLAGS(uart), &f); //NOLINT - complaint in external macro
f &= ~AVR_UART_FLAG_POLL_SLEEP; // Issue #356
avr_ioctl(m_pAVR, AVR_IOCTL_UART_SET_FLAGS(uart), &f); //NOLINT - complaint in external macro

RegisterNotify(BYTE_IN, MAKE_C_CALLBACK(uart_pty,OnByteIn), this);

int hastap = (getenv("SIMAVR_UART_TAP") && stoi(getenv("SIMAVR_UART_TAP"))) ||
Expand Down Expand Up @@ -313,6 +309,30 @@ void uart_pty::Init(struct avr_t * avr, char uart)

}

void uart_pty::BypassXON()
{
OnXOnIn(nullptr, 0);
}

void uart_pty::Init(struct avr_t * avr)
{
_Init(avr,this);
InitPrivate();
BypassXON();
}

void uart_pty::Init(struct avr_t * avr, char uart)
{
_Init(avr,this);
uint32_t f = 0;
avr_ioctl(m_pAVR, AVR_IOCTL_UART_GET_FLAGS(uart), &f); //NOLINT - complaint in external macro
f &= ~AVR_UART_FLAG_POLL_SLEEP; // Issue #356
avr_ioctl(m_pAVR, AVR_IOCTL_UART_SET_FLAGS(uart), &f); //NOLINT - complaint in external macro

InitPrivate();

}

// Shuts down the thread on destruction.
uart_pty::~uart_pty()
{
Expand Down Expand Up @@ -352,24 +372,23 @@ void uart_pty::Connect(char uart)
if (xon) avr_irq_register_notify(xon, MAKE_C_CALLBACK(uart_pty,OnXOnIn), this);
if (xoff) avr_irq_register_notify(xoff, MAKE_C_CALLBACK(uart_pty,OnXOffIn),this);

//for (int ti = 0; ti < 1; ti++)
if (port[0].s) {
std::string strLnk("/tmp/simavr-uart");
// if (ti==1)
// {
// strLnk +="tap";
// }
strLnk+=uart;
unlink(strLnk.c_str());
if (symlink(static_cast<char*>(port[0].slavename), strLnk.c_str()) != 0)
{
std::cerr << "WARN: Can't create " << strLnk << " " << strerror(errno);
}
else
{
std::cout << strLnk << " now points to: " << static_cast<char*>(port[0].slavename) << '\n';
}
if (port[0].s) {
std::string strLnk("/tmp/simavr-uart");
// if (ti==1)
// {
// strLnk +="tap";
// }
strLnk+=uart;
unlink(strLnk.c_str());
if (symlink(static_cast<char*>(port[0].slavename), strLnk.c_str()) != 0)
{
std::cerr << "WARN: Can't create " << strLnk << " " << strerror(errno);
}
else
{
std::cout << strLnk << " now points to: " << static_cast<char*>(port[0].slavename) << '\n';
}
}
if (getenv("SIMAVR_UART_XTERM") && stoi(getenv("SIMAVR_UART_XTERM")))
{
std::string strCmd("xterm -e picocom -b 115200 ");
Expand All @@ -385,3 +404,18 @@ void uart_pty::Connect(char uart)
std::cout << "note: export SIMAVR_UART_XTERM=1 and install picocom to get a terminal\n";
}
}

void uart_pty::ConnectPTYOnly(const std::string& strLnk)
{
if (port[0].s) {
unlink(strLnk.c_str());
if (symlink(static_cast<char*>(port[0].slavename), strLnk.c_str()) != 0)
{
std::cerr << "WARN: Can't create " << strLnk << " " << strerror(errno);
}
else
{
std::cout << strLnk << " now points to: " << static_cast<char*>(port[0].slavename) << '\n';
}
}
}
12 changes: 12 additions & 0 deletions parts/components/uart_pty.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,18 @@ class uart_pty: public BasePeripheral
// Registers with SimAVR
void Init(avr_t *avr, char uart);

// Registers a dummy UART PTY that isn't connected to the AVR.
void Init(avr_t *avr);

// Actually connects to the UART.
void Connect(char chrUART);

// Sets up a PTY but does nothing else.
void ConnectPTYOnly(const std::string& strLnk);

// Used to disable XON for PTY-only connections.
void BypassXON();

// Resets the newline trap after a printer reset.
inline void Reset() { m_chrLast = '\n';}

Expand All @@ -70,6 +79,9 @@ class uart_pty: public BasePeripheral

private:

// Registers a dummy UART PTY that isn't connected to the AVR.
void InitPrivate();

void* Run();
void OnByteIn(avr_irq_t * irq, uint32_t value);
void OnXOnIn(avr_irq_t * irq, uint32_t value);
Expand Down
2 changes: 1 addition & 1 deletion parts/printers/Prusa_MMU2.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Prusa_MMU2 : public Printer, public MMU2
{
public:

Prusa_MMU2():MMU2(false){};
Prusa_MMU2():MMU2(false, true){};


inline std::pair<int,int> GetWindowSize() override;
Expand Down
Loading

0 comments on commit 6f034c9

Please sign in to comment.