Move ring buffer implemented and (preliminarily) tested. Look ahead not yet done.

This commit is contained in:
Adrian Bowyer 2013-05-24 22:03:48 +01:00
parent 080443f0f4
commit 557ea85073
3 changed files with 81 additions and 76 deletions

119
Move.h
View file

@ -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;
} }

View file

@ -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)
{
for(char i = 0; i < AXES; i++) if(ddaRingBuffer->Add(currentPosition, nextMove, u, v))
currentPosition[i] = nextMove[i]; {
for(char i = 0; i < AXES; i++)
currentPosition[i] = nextMove[i];
currentFeedrate = nextMove[DRIVES];
moveWaiting = false;
}
return;
}
if(work) moveWaiting = gCodes->ReadMove(nextMove);
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);
} }
//**************************************************************************************************** //****************************************************************************************************

View file

@ -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)