Skip to content

Commit 6f034c9

Browse files
authored
Add sideband control PTY for FS and reset lines (#374)
* Add sideband control PTY for FS and reset lines * Add sideband test coverage for MMU2
1 parent faf2283 commit 6f034c9

File tree

10 files changed

+263
-38
lines changed

10 files changed

+263
-38
lines changed

parts/Board.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,11 @@ namespace Boards
8181
inline std::string GetSDCardFile(){return m_strSDFile.empty()?GetStorageFileName("SDcard"):m_strSDFile;}
8282

8383
inline void SetResetFlag(){m_bReset = true;}
84+
inline bool GetResetFlag(){return m_bReset;}
8485
inline void SetQuitFlag(){m_bQuit = true; m_bPaused = false;}
8586
inline bool GetQuitFlag(){return m_bQuit;}
8687

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

parts/boards/MM_Control_01.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ namespace Boards
3939
#endif
4040
}
4141

42+
void MM_Control_01::OnAVRReset()
43+
{
44+
if (m_bSidebandInit)
45+
{
46+
std::cout << "Sideband reset complete\n";
47+
m_USideband.BypassXON();
48+
}
49+
}
50+
51+
void MM_Control_01::SetupSideband()
52+
{
53+
m_USideband.Init(m_pAVR);
54+
m_USideband.ConnectPTYOnly("/tmp/MK404-MMU-sideband");
55+
m_bSidebandInit = true;
56+
}
57+
4258
void MM_Control_01::SetupHardware()
4359
{
4460
DisableInterruptLevelPoll(5);

parts/boards/MM_Control_01.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,18 @@ namespace Boards
4747
void Draw(float fY);
4848

4949
protected:
50+
51+
void OnAVRReset() override;
52+
5053
void SetupHardware() override;
5154

55+
void SetupSideband();
5256

5357
// void CustomAVRInit() override;
5458

5559
// void CustomAVRDeinit() override;
5660

57-
uart_pty m_UART;
61+
uart_pty m_UART, m_USideband;
5862
HC595 m_shift;
5963
TMC2130 m_Sel {'S'},
6064
m_Idl {'I'},
@@ -73,5 +77,7 @@ namespace Boards
7377
const Wirings::MM_Control_01 m_wiring = Wirings::MM_Control_01();
7478

7579
std::string m_strTitle = "Missing Material Unit 2";
80+
81+
bool m_bSidebandInit = false;
7682
};
7783
}; // namespace Boards

parts/components/MMU2.cpp

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "IKeyClient.h"
2626
#include "LED.h" // for LED
2727
#include "MM_Control_01.h" // for MM_Control_01
28+
#include "MMUSideband.h"
2829
#include "PinNames.h" // for Pin::FINDA_PIN
2930
#include "TMC2130.h" // for TMC2130
3031
#include "gsl-lite.hpp"
@@ -40,7 +41,7 @@ MMU2 *MMU2::g_pMMU = nullptr;
4041

4142
using Boards::MM_Control_01;
4243

43-
MMU2::MMU2(bool bCreate):IKeyClient(),MM_Control_01()
44+
MMU2::MMU2(bool bCreate, bool bSetupSB):IKeyClient(),MM_Control_01(),m_bSidebandEnabled(bSetupSB)
4445
{
4546
if (g_pMMU)
4647
{
@@ -128,18 +129,23 @@ void MMU2::SetupHardware()
128129
m_Idl.ConnectTo(TMC2130::POSITION_OUT,GetIRQ(IDLER_OUT));
129130
m_Extr.ConnectTo(TMC2130::POSITION_OUT,GetIRQ(PULLEY_IN));
130131
m_shift.ConnectTo(HC595::SHIFT_OUT, GetIRQ(SHIFT_IN));
132+
133+
if (m_bSidebandEnabled)
134+
{
135+
SetupSidebandControl();
136+
}
131137
}
132138

133139

134140
void MMU2::OnResetIn(struct avr_irq_t *irq, uint32_t value)
135141
{
136-
if (!value && !m_bStarted)
142+
if (!value && !IsStarted())
137143
{
138144
StartAVR();
139145
}
140146
else if (irq->value && !value)
141147
{
142-
m_bReset = true;
148+
SetResetFlag();
143149
}
144150
}
145151

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

160+
void MMU2::SetupSidebandControl()
161+
{
162+
MM_Control_01::SetupSideband();
163+
RegisterNotify(SB_BYTE_IN, MAKE_C_CALLBACK(MMU2, OnSidebandByteIn), this);
164+
ConnectTo(SB_FS, m_USideband.GetIRQ(uart_pty::BYTE_IN));
165+
ConnectFrom(m_USideband.GetIRQ(uart_pty::BYTE_OUT), SB_BYTE_IN);
166+
}
167+
168+
void MMU2::OnSidebandByteIn(struct avr_irq_t * ,uint32_t value)
169+
{
170+
switch (value)
171+
{
172+
case MMUSideband::RESET:
173+
std::cout << "MMU Received sideband RESET signal\n";
174+
RaiseIRQ(RESET,1);
175+
RaiseIRQ(RESET,0);
176+
break;
177+
default:
178+
std::cerr << "Unrecognized sideband control character:" << (char)value << "\n";
179+
break;
180+
}
181+
}
182+
154183
void MMU2::OnPulleyFeedIn(struct avr_irq_t * ,uint32_t value)
155184
{
156185
float posOut;
157186
std::memcpy(&posOut, &value,4);
158187

159188
if (m_bAutoFINDA)
160189
{
161-
SetPin(FINDA_PIN,posOut>33.0f);
190+
SetPin(FINDA_PIN, posOut > FINDA_TRIGGER_DISTANCE);
162191
// Reflect the distance out for IR sensor triggering.
163192
RaiseIRQ(FEED_DISTANCE, value);
164-
RaiseIRQ(FINDA_OUT,posOut>33.f);
193+
RaiseIRQ(FINDA_OUT, posOut > FINDA_TRIGGER_DISTANCE);
194+
195+
if (m_bSidebandEnabled)
196+
{
197+
if (m_fLastPosOut < FSENSOR_TRIGGER_DISTANCE && posOut >= FSENSOR_TRIGGER_DISTANCE)
198+
{
199+
RaiseIRQ(SB_FS, MMUSideband::FS_AUTO_SET);
200+
}
201+
else if (m_fLastPosOut >= FSENSOR_TRIGGER_DISTANCE && posOut < FSENSOR_TRIGGER_DISTANCE)
202+
{
203+
RaiseIRQ(SB_FS, MMUSideband::FS_AUTO_CLEAR);
204+
}
205+
m_fLastPosOut = posOut;
206+
}
165207
}
166208
else
167209
{

parts/components/MMU2.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ class MMU2: public BasePeripheral, public Boards::MM_Control_01, virtual private
3939
public:
4040
#define IRQPAIRS _IRQ(FEED_DISTANCE,"<mmu.feed_distance") _IRQ(RESET,"<mmu.reset") _IRQ(PULLEY_IN,"<mmu.pulley_in") \
4141
_IRQ(SELECTOR_OUT,">sel_pos.out") _IRQ(IDLER_OUT,">idler_pos.out") _IRQ(LEDS_OUT,">leds.out") _IRQ(FINDA_OUT,">finda.out") \
42-
_IRQ(SHIFT_IN,"<32shift.in")
42+
_IRQ(SHIFT_IN,"<32shift.in") _IRQ(SB_FS, ">sideband_fs.out") _IRQ(SB_BYTE_IN, "sideband_byte.in")
4343
#include "IRQHelper.h"
4444

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

4848
~MMU2() override {StopAVR();}
4949

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

56+
5657
protected:
58+
59+
static constexpr float FINDA_TRIGGER_DISTANCE = 33.f;
60+
static constexpr float FSENSOR_TRIGGER_DISTANCE = 400.f;
61+
62+
#ifdef TEST_MODE
63+
friend void Test_MMU2_internal();
64+
#endif
65+
5766
enum Actions
5867
{
5968
// We have to extend board rather than being our own IScriptable due
@@ -71,19 +80,21 @@ class MMU2: public BasePeripheral, public Boards::MM_Control_01, virtual private
7180

7281
private:
7382

74-
void* Run();
83+
void SetupSidebandControl();
7584

7685
void OnResetIn(avr_irq_t *irq, uint32_t value);
7786

7887
void OnPulleyFeedIn(avr_irq_t *irq, uint32_t value);
7988

8089
void LEDHandler(avr_irq_t *irq, uint32_t value);
8190

91+
void OnSidebandByteIn(avr_irq_t *irq, uint32_t value);
92+
8293
std::atomic_bool m_bAutoFINDA = {true};
8394
std::atomic_bool m_bFINDAManual = {false};
84-
std::atomic_bool m_bStarted = {false};
85-
std::atomic_bool m_bReset ={false};
86-
pthread_t m_tRun = 0;
95+
96+
bool m_bSidebandEnabled = false;
97+
float m_fLastPosOut = 0;
8798

8899
static MMU2 *g_pMMU; // Needed for GL
89100
};

parts/components/uart_pty.cpp

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ int
5757
//#define TRACE(_w) _w
5858
#ifndef TRACE
5959
#define TRACE(_w)
60+
#else
61+
#include "sim_hex.h"
6062
#endif
6163

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

281-
void uart_pty::Init(struct avr_t * avr, char uart)
283+
void uart_pty::InitPrivate()
282284
{
283-
_Init(avr,this);
284-
uint32_t f = 0;
285-
avr_ioctl(m_pAVR, AVR_IOCTL_UART_GET_FLAGS(uart), &f); //NOLINT - complaint in external macro
286-
f &= ~AVR_UART_FLAG_POLL_SLEEP; // Issue #356
287-
avr_ioctl(m_pAVR, AVR_IOCTL_UART_SET_FLAGS(uart), &f); //NOLINT - complaint in external macro
288-
289285
RegisterNotify(BYTE_IN, MAKE_C_CALLBACK(uart_pty,OnByteIn), this);
290286

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

314310
}
315311

312+
void uart_pty::BypassXON()
313+
{
314+
OnXOnIn(nullptr, 0);
315+
}
316+
317+
void uart_pty::Init(struct avr_t * avr)
318+
{
319+
_Init(avr,this);
320+
InitPrivate();
321+
BypassXON();
322+
}
323+
324+
void uart_pty::Init(struct avr_t * avr, char uart)
325+
{
326+
_Init(avr,this);
327+
uint32_t f = 0;
328+
avr_ioctl(m_pAVR, AVR_IOCTL_UART_GET_FLAGS(uart), &f); //NOLINT - complaint in external macro
329+
f &= ~AVR_UART_FLAG_POLL_SLEEP; // Issue #356
330+
avr_ioctl(m_pAVR, AVR_IOCTL_UART_SET_FLAGS(uart), &f); //NOLINT - complaint in external macro
331+
332+
InitPrivate();
333+
334+
}
335+
316336
// Shuts down the thread on destruction.
317337
uart_pty::~uart_pty()
318338
{
@@ -352,24 +372,23 @@ void uart_pty::Connect(char uart)
352372
if (xon) avr_irq_register_notify(xon, MAKE_C_CALLBACK(uart_pty,OnXOnIn), this);
353373
if (xoff) avr_irq_register_notify(xoff, MAKE_C_CALLBACK(uart_pty,OnXOffIn),this);
354374

355-
//for (int ti = 0; ti < 1; ti++)
356-
if (port[0].s) {
357-
std::string strLnk("/tmp/simavr-uart");
358-
// if (ti==1)
359-
// {
360-
// strLnk +="tap";
361-
// }
362-
strLnk+=uart;
363-
unlink(strLnk.c_str());
364-
if (symlink(static_cast<char*>(port[0].slavename), strLnk.c_str()) != 0)
365-
{
366-
std::cerr << "WARN: Can't create " << strLnk << " " << strerror(errno);
367-
}
368-
else
369-
{
370-
std::cout << strLnk << " now points to: " << static_cast<char*>(port[0].slavename) << '\n';
371-
}
375+
if (port[0].s) {
376+
std::string strLnk("/tmp/simavr-uart");
377+
// if (ti==1)
378+
// {
379+
// strLnk +="tap";
380+
// }
381+
strLnk+=uart;
382+
unlink(strLnk.c_str());
383+
if (symlink(static_cast<char*>(port[0].slavename), strLnk.c_str()) != 0)
384+
{
385+
std::cerr << "WARN: Can't create " << strLnk << " " << strerror(errno);
386+
}
387+
else
388+
{
389+
std::cout << strLnk << " now points to: " << static_cast<char*>(port[0].slavename) << '\n';
372390
}
391+
}
373392
if (getenv("SIMAVR_UART_XTERM") && stoi(getenv("SIMAVR_UART_XTERM")))
374393
{
375394
std::string strCmd("xterm -e picocom -b 115200 ");
@@ -385,3 +404,18 @@ void uart_pty::Connect(char uart)
385404
std::cout << "note: export SIMAVR_UART_XTERM=1 and install picocom to get a terminal\n";
386405
}
387406
}
407+
408+
void uart_pty::ConnectPTYOnly(const std::string& strLnk)
409+
{
410+
if (port[0].s) {
411+
unlink(strLnk.c_str());
412+
if (symlink(static_cast<char*>(port[0].slavename), strLnk.c_str()) != 0)
413+
{
414+
std::cerr << "WARN: Can't create " << strLnk << " " << strerror(errno);
415+
}
416+
else
417+
{
418+
std::cout << strLnk << " now points to: " << static_cast<char*>(port[0].slavename) << '\n';
419+
}
420+
}
421+
}

parts/components/uart_pty.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,18 @@ class uart_pty: public BasePeripheral
5959
// Registers with SimAVR
6060
void Init(avr_t *avr, char uart);
6161

62+
// Registers a dummy UART PTY that isn't connected to the AVR.
63+
void Init(avr_t *avr);
64+
6265
// Actually connects to the UART.
6366
void Connect(char chrUART);
6467

68+
// Sets up a PTY but does nothing else.
69+
void ConnectPTYOnly(const std::string& strLnk);
70+
71+
// Used to disable XON for PTY-only connections.
72+
void BypassXON();
73+
6574
// Resets the newline trap after a printer reset.
6675
inline void Reset() { m_chrLast = '\n';}
6776

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

7180
private:
7281

82+
// Registers a dummy UART PTY that isn't connected to the AVR.
83+
void InitPrivate();
84+
7385
void* Run();
7486
void OnByteIn(avr_irq_t * irq, uint32_t value);
7587
void OnXOnIn(avr_irq_t * irq, uint32_t value);

parts/printers/Prusa_MMU2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class Prusa_MMU2 : public Printer, public MMU2
2929
{
3030
public:
3131

32-
Prusa_MMU2():MMU2(false){};
32+
Prusa_MMU2():MMU2(false, true){};
3333

3434

3535
inline std::pair<int,int> GetWindowSize() override;

0 commit comments

Comments
 (0)