diff --git a/Configuration.h b/Configuration.h index 87077cd..66ac2f1 100644 --- a/Configuration.h +++ b/Configuration.h @@ -58,5 +58,8 @@ Licence: GPL #define START_FEED_RATE 200 #define GCODE_LENGTH 100 // Maximum lenght of internally-generated G Code string +// Movement stuff + +#define RING_LENGTH 10 #endif diff --git a/Move.h b/Move.h index 80dd925..f789247 100644 --- a/Move.h +++ b/Move.h @@ -53,6 +53,64 @@ class DDA volatile boolean active; }; +//********************************************************************************************* + +/* + + 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 +{ + public: + DDARingBuffer(Move* m, Platform* p); + void Add(float currentPosition[], float targetPosition[], float& u, float& v); + DDA* Get(); + boolean Empty(); + boolean Full(); + boolean getLock(); + void releaseLock(); + + private: + Platform* platform; + DDA* ring[RING_LENGTH]; + volatile char addPointer; + volatile char getPointer; + volatile boolean locked; +}; + +//************************************************************************************************** + class Move { public: @@ -81,6 +139,8 @@ class Move float extruderStepDistances[(1<<(DRIVES-AXES))]; // NB - limits us to 5 extruders }; +//******************************************************************************************************** + inline boolean DDA::Active() { return active; @@ -91,6 +151,70 @@ inline boolean DDA::VelocitiesAltered() return velocitiesAltered; } +//***************************************************************************************************** + +inline boolean DDARingBuffer::getLock() +{ + if(locked) + return false; + locked = true; + return true; +} + +inline void DDARingBuffer::releaseLock() +{ + if(!locked) + platform->Message(HOST_MESSAGE, "Attempt to unlock already unlocked ring buffer.\n"); + locked = false; + return; +} + +inline void DDARingBuffer::Add(float currentPosition[], float targetPosition[], float& u, float& v) +{ + if(Full()) + { + platform->Message(HOST_MESSAGE, "Attempt to overfill ring buffer.\n"); + return; + } + + ring[addPointer]->Init(currentPosition, targetPosition, u, v); + addPointer++; + if(addPointer >= RING_LENGTH) + addPointer = 0; +} + +inline DDA* DDARingBuffer::Get() +{ + if(Empty()) + { + platform->Message(HOST_MESSAGE, "Attempt to use empty ring buffer.\n"); + return ring[getPointer]; // Safer than NULL + } + DDA* d = ring[getPointer]; + getPointer++; + if(getPointer >= RING_LENGTH) + getPointer = 0; + return d; +} + +inline boolean DDARingBuffer::Empty() +{ + return getPointer == addPointer; +} + +// Leave a gap of 2 as the last Get result may still be being processed + +inline boolean DDARingBuffer::Full() +{ + if(getPointer == 0) + return addPointer == RING_LENGTH - 2; + if(getPointer == 1) + return addPointer == RING_LENGTH - 1; + return addPointer == getPointer - 2; +} + +//********************************************************************************************** + inline void Move::Interrupt() { dda->Step(true); diff --git a/Move.ino b/Move.ino index 29f6caf..be967a6 100644 --- a/Move.ino +++ b/Move.ino @@ -414,3 +414,16 @@ void DDA::Step(boolean noTest) if(!active && noTest) //??? platform->SetInterrupt(-1); } + +//**************************************************************************************************** + +DDARingBuffer::DDARingBuffer(Move* m, Platform* p) +{ + platform = p; + for(addPointer = 0; addPointer < RING_LENGTH; addPointer++) + ring[addPointer] = new DDA(m, p); + addPointer = 0; + getPointer = 0; + locked = false; +} + diff --git a/RepRapFirmware.ino b/RepRapFirmware.ino index a823f77..ee045c8 100644 --- a/RepRapFirmware.ino +++ b/RepRapFirmware.ino @@ -100,6 +100,10 @@ void RepRap::Spin() heat->Spin(); } +// This function is never normally called. It is a test to time +// the interrupt function. To activate it, uncomment the line that calls +// this in Platform.ino. + void RepRap::InterruptTime() { char buffer[50]; @@ -125,6 +129,9 @@ void RepRap::InterruptTime() // Utilities and storage not part of any class + +// Float to a string. + static long precision[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000}; char* ftoa(char *a, const float& f, int prec)