Move ring buffer implemented and (preliminarily) tested. Look ahead not yet done.
This commit is contained in:
parent
080443f0f4
commit
557ea85073
3 changed files with 81 additions and 76 deletions
117
Move.h
117
Move.h
|
@ -55,53 +55,19 @@ class DDA
|
||||||
|
|
||||||
//*********************************************************************************************
|
//*********************************************************************************************
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
To call the RingBuffer functions the sequences are:
|
|
||||||
|
|
||||||
Get:
|
|
||||||
|
|
||||||
if(ringBuffer->getLock())
|
|
||||||
{
|
|
||||||
if(ringBuffer->Empty())
|
|
||||||
{
|
|
||||||
ringBuffer->releaseLock();
|
|
||||||
// Nothing there - go and do something else...
|
|
||||||
}
|
|
||||||
d = Get();
|
|
||||||
ringBuffer->releaseLock();
|
|
||||||
// Do something with d and don't do another Get until you have finished with d...
|
|
||||||
}
|
|
||||||
|
|
||||||
Add:
|
|
||||||
|
|
||||||
if(ringBuffer->getLock())
|
|
||||||
{
|
|
||||||
if(ringBuffer->Full())
|
|
||||||
{
|
|
||||||
ringBuffer->releaseLock();
|
|
||||||
// No room - come back later...
|
|
||||||
}
|
|
||||||
ringBuffer->Add(...);
|
|
||||||
ringBuffer->releaseLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
class DDARingBuffer
|
class DDARingBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DDARingBuffer(Move* m, Platform* p);
|
DDARingBuffer(Move* m, Platform* p);
|
||||||
void Add(float currentPosition[], float targetPosition[], float& u, float& v);
|
boolean Add(float currentPosition[], float targetPosition[], float& u, float& v);
|
||||||
DDA* Get();
|
DDA* Get();
|
||||||
|
|
||||||
|
private:
|
||||||
boolean Empty();
|
boolean Empty();
|
||||||
boolean Full();
|
boolean Full();
|
||||||
boolean getLock();
|
boolean getLock();
|
||||||
void releaseLock();
|
void releaseLock();
|
||||||
|
|
||||||
private:
|
|
||||||
Platform* platform;
|
Platform* platform;
|
||||||
DDA* ring[RING_LENGTH];
|
DDA* ring[RING_LENGTH];
|
||||||
volatile char addPointer;
|
volatile char addPointer;
|
||||||
|
@ -130,8 +96,10 @@ class Move
|
||||||
Platform* platform;
|
Platform* platform;
|
||||||
GCodes* gCodes;
|
GCodes* gCodes;
|
||||||
DDA* dda;
|
DDA* dda;
|
||||||
|
DDARingBuffer* ddaRingBuffer;
|
||||||
unsigned long lastTime;
|
unsigned long lastTime;
|
||||||
boolean active;
|
boolean active;
|
||||||
|
boolean moveWaiting;
|
||||||
float currentFeedrate;
|
float currentFeedrate;
|
||||||
float currentPosition[AXES]; // Note - drives above AXES are always relative moves
|
float currentPosition[AXES]; // Note - drives above AXES are always relative moves
|
||||||
float nextMove[DRIVES + 1]; // Extra is for feedrate
|
float nextMove[DRIVES + 1]; // Extra is for feedrate
|
||||||
|
@ -164,37 +132,60 @@ inline boolean DDARingBuffer::getLock()
|
||||||
inline void DDARingBuffer::releaseLock()
|
inline void DDARingBuffer::releaseLock()
|
||||||
{
|
{
|
||||||
if(!locked)
|
if(!locked)
|
||||||
platform->Message(HOST_MESSAGE, "Attempt to unlock already unlocked ring buffer.\n");
|
platform->Message(HOST_MESSAGE, "Attempt to unlock an already unlocked ring buffer!\n");
|
||||||
locked = false;
|
locked = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DDARingBuffer::Add(float currentPosition[], float targetPosition[], float& u, float& v)
|
inline boolean DDARingBuffer::Add(float currentPosition[], float targetPosition[], float& u, float& v)
|
||||||
{
|
{
|
||||||
if(Full())
|
if(getLock())
|
||||||
{
|
{
|
||||||
platform->Message(HOST_MESSAGE, "Attempt to overfill ring buffer.\n");
|
if(Full())
|
||||||
return;
|
{
|
||||||
|
releaseLock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(ring[addPointer]->Active())
|
||||||
|
{
|
||||||
|
platform->Message(HOST_MESSAGE, "Attempt to alter an active ring buffer entry!\n");
|
||||||
|
releaseLock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!ring[addPointer]->Init(currentPosition, targetPosition, u, v))
|
||||||
|
{
|
||||||
|
// Throw it away
|
||||||
|
releaseLock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
addPointer++;
|
||||||
|
if(addPointer >= RING_LENGTH)
|
||||||
|
addPointer = 0;
|
||||||
|
releaseLock();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
ring[addPointer]->Init(currentPosition, targetPosition, u, v);
|
|
||||||
addPointer++;
|
|
||||||
if(addPointer >= RING_LENGTH)
|
|
||||||
addPointer = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline DDA* DDARingBuffer::Get()
|
inline DDA* DDARingBuffer::Get()
|
||||||
{
|
{
|
||||||
if(Empty())
|
DDA* result = NULL;
|
||||||
|
if(getLock())
|
||||||
{
|
{
|
||||||
platform->Message(HOST_MESSAGE, "Attempt to use empty ring buffer.\n");
|
if(Empty())
|
||||||
return ring[getPointer]; // Safer than NULL
|
{
|
||||||
|
releaseLock();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result = ring[getPointer];
|
||||||
|
getPointer++;
|
||||||
|
if(getPointer >= RING_LENGTH)
|
||||||
|
getPointer = 0;
|
||||||
|
releaseLock();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
DDA* d = ring[getPointer];
|
return NULL;
|
||||||
getPointer++;
|
|
||||||
if(getPointer >= RING_LENGTH)
|
|
||||||
getPointer = 0;
|
|
||||||
return d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline boolean DDARingBuffer::Empty()
|
inline boolean DDARingBuffer::Empty()
|
||||||
|
@ -217,7 +208,21 @@ inline boolean DDARingBuffer::Full()
|
||||||
|
|
||||||
inline void Move::Interrupt()
|
inline void Move::Interrupt()
|
||||||
{
|
{
|
||||||
dda->Step(true);
|
if(dda == NULL)
|
||||||
|
{
|
||||||
|
dda = ddaRingBuffer->Get();
|
||||||
|
if(dda != NULL)
|
||||||
|
dda->Start(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dda->Active())
|
||||||
|
{
|
||||||
|
dda->Step(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dda = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
29
Move.ino
29
Move.ino
|
@ -25,7 +25,8 @@ Move::Move(Platform* p, GCodes* g)
|
||||||
active = false;
|
active = false;
|
||||||
platform = p;
|
platform = p;
|
||||||
gCodes = g;
|
gCodes = g;
|
||||||
dda = new DDA(this, platform);
|
dda = NULL;
|
||||||
|
ddaRingBuffer = new DDARingBuffer(this, platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Move::Init()
|
void Move::Init()
|
||||||
|
@ -80,6 +81,7 @@ void Move::Init()
|
||||||
|
|
||||||
lastTime = platform->Time();
|
lastTime = platform->Time();
|
||||||
currentFeedrate = START_FEED_RATE;
|
currentFeedrate = START_FEED_RATE;
|
||||||
|
moveWaiting = false;
|
||||||
active = true;
|
active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,20 +100,23 @@ void Move::Spin()
|
||||||
|
|
||||||
void Move::Qmove()
|
void Move::Qmove()
|
||||||
{
|
{
|
||||||
if(!gCodes->ReadMove(nextMove))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//FIXME
|
//FIXME
|
||||||
float u = 0.0; // This will provoke the code to select the jerk values.
|
float u = 0.0; // This will provoke the code to select the jerk values.
|
||||||
float v = 0.0;
|
float v = 0.0;
|
||||||
|
|
||||||
boolean work = dda->Init(currentPosition, nextMove, u, v);
|
if(moveWaiting)
|
||||||
|
{
|
||||||
|
if(ddaRingBuffer->Add(currentPosition, nextMove, u, v))
|
||||||
|
{
|
||||||
|
for(char i = 0; i < AXES; i++)
|
||||||
|
currentPosition[i] = nextMove[i];
|
||||||
|
currentFeedrate = nextMove[DRIVES];
|
||||||
|
moveWaiting = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(char i = 0; i < AXES; i++)
|
moveWaiting = gCodes->ReadMove(nextMove);
|
||||||
currentPosition[i] = nextMove[i];
|
|
||||||
|
|
||||||
if(work)
|
|
||||||
dda->Start(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Move::GetCurrentState(float m[])
|
void Move::GetCurrentState(float m[])
|
||||||
|
@ -411,8 +416,8 @@ void DDA::Step(boolean noTest)
|
||||||
stepCount++;
|
stepCount++;
|
||||||
active = stepCount < totalSteps;
|
active = stepCount < totalSteps;
|
||||||
|
|
||||||
if(!active && noTest) //???
|
if(!active && noTest)
|
||||||
platform->SetInterrupt(-1);
|
platform->SetInterrupt(STANDBY_INTERRUPT_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//****************************************************************************************************
|
//****************************************************************************************************
|
||||||
|
|
|
@ -152,15 +152,10 @@ Licence: GPL
|
||||||
|
|
||||||
#define BAUD_RATE 115200 // Communication speed of the USB if needed.
|
#define BAUD_RATE 115200 // Communication speed of the USB if needed.
|
||||||
|
|
||||||
|
#define STANDBY_INTERRUPT_RATE 200 // Microseconds
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************************************/
|
/****************************************************************************************************/
|
||||||
|
|
||||||
//class RepRap;
|
|
||||||
|
|
||||||
void TC3_Handler();
|
|
||||||
|
|
||||||
class Platform
|
class Platform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -388,7 +383,7 @@ void Platform::InitialiseInterrupts()
|
||||||
TC_Configure(TC1, 0, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
|
TC_Configure(TC1, 0, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
|
||||||
TC1->TC_CHANNEL[0].TC_IER=TC_IER_CPCS;
|
TC1->TC_CHANNEL[0].TC_IER=TC_IER_CPCS;
|
||||||
TC1->TC_CHANNEL[0].TC_IDR=~TC_IER_CPCS;
|
TC1->TC_CHANNEL[0].TC_IDR=~TC_IER_CPCS;
|
||||||
NVIC_DisableIRQ(TC3_IRQn);
|
SetInterrupt(STANDBY_INTERRUPT_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Platform::SetInterrupt(long t)
|
inline void Platform::SetInterrupt(long t)
|
||||||
|
|
Reference in a new issue