add job queue to stepticker.
authorJim Morris <morris@wolfman.com>
Sun, 15 May 2016 06:41:39 +0000 (23:41 -0700)
committerJim Morris <morris@wolfman.com>
Sun, 15 May 2016 06:41:39 +0000 (23:41 -0700)
remove unused data from steppermotor

src/libs/StepTicker.cpp
src/libs/StepTicker.h
src/libs/StepperMotor.cpp
src/libs/StepperMotor.h
src/modules/robot/Stepper.cpp
src/modules/utils/motordrivercontrol/drivers/TMC26X/TMC26X.cpp

index c2ab16f..5963e01 100644 (file)
@@ -48,7 +48,6 @@ StepTicker::StepTicker()
     this->num_motors = 0;
 
     this->move_issued = false;
-    this->next_block = nullptr;
 }
 
 StepTicker::~StepTicker()
@@ -122,15 +121,18 @@ void StepTicker::step_tick (void)
 {
     static uint32_t current_tick = 0;
 
-    if(!move_issued) return; // if nothing has been setup we ignore the ticks
+    if(!move_issued){
+        if(jobq.empty()) return; // if nothing has been setup we ignore the ticks
+        // get next job, and copy data
+        Block *b= nullptr;
+        jobq.get(b);
+        copy_block(b);
+    }
 
     current_tick++; // count number of ticks
 
     bool still_moving = false;
 
-    // currently taking 13us when no step, and 20 when 1 step
-    // 21us when two motors and 36 when step
-    stepticker_debug_pin = 1;
     // foreach motor, if it is active see if time to issue a step to that motor
     for (uint8_t m = 0; m < num_motors; m++) {
         if(tick_info[m].steps_to_move == 0) continue; // not active
@@ -178,7 +180,6 @@ void StepTicker::step_tick (void)
             }
         }
     }
-    stepticker_debug_pin = 0;
 
     // We may have set a pin on in this tick, now we reset the timer to set it off
     // Note there could be a race here if we run another tick before the unsteps have happened,
@@ -195,18 +196,20 @@ void StepTicker::step_tick (void)
 
         // get next static block and tick info from next block
         // do it here so there is no delay in ticks
-        if(next_block != nullptr) {
+        if(!jobq.empty()) {
             #ifdef STEPTICKER_DEBUG_PIN
             stepticker_debug_pin = 1;
             #endif
 
-            // copy data
-            copy_block(next_block);
-            next_block = nullptr;
+            // get next job, and copy data
+            Block *b= nullptr;
+            jobq.get(b);
+            copy_block(b);
 
             #ifdef STEPTICKER_DEBUG_PIN
             stepticker_debug_pin = 0;
             #endif
+
         } else {
             move_issued = false; // nothing to do as no more blocks
         }
@@ -221,6 +224,7 @@ void StepTicker::step_tick (void)
 // called in ISR if running, else can be called from anything to start
 void StepTicker::copy_block(Block *block)
 {
+    stepticker_debug_pin = 1;
     block_info.accelerate_until = block->accelerate_until;
     block_info.decelerate_after = block->decelerate_after;
     block_info.total_move_ticks = block->total_move_ticks;
@@ -260,6 +264,7 @@ void StepTicker::copy_block(Block *block)
         tick_info[m].plateau_rate= floorf(((block->maximum_rate * aratio) / frequency) * (1<<30));
     }
     move_issued = true;
+    stepticker_debug_pin = 0;
 }
 
 // returns index of the stepper motor in the array and bitset
index d5ac65a..e26547d 100644 (file)
@@ -29,15 +29,15 @@ class StepTicker{
         void set_unstep_time( float microseconds );
         int register_motor(StepperMotor* motor);
         float get_frequency() const { return frequency; }
-
+        bool is_moving(int i) const { return tick_info[i].steps_to_move != 0; }
+        uint32_t get_stepped(int i) const { return tick_info[i].step_count; }
         void unstep_tick();
         void step_tick (void);
         void handle_finish (void);
 
         void start();
-        void copy_block(Block *block);
-        void set_next_block(Block *block) { next_block= block; }
-        bool is_next_block() const { return next_block != nullptr; }
+        bool add_job(Block *block) { return jobq.put(block); }
+        bool is_jobq_full() const { return jobq.full(); }
 
         // whatever setup the block should register this to know when it is done
         std::function<void()> finished_fnc{nullptr};
@@ -47,6 +47,71 @@ class StepTicker{
     private:
         static StepTicker *instance;
 
+            //
+            //  Simple fixed size ring buffer.
+            //  Manage objects by value.
+            //  Thread safe for single Producer and single Consumer.
+            //  By Dennis Lang http://home.comcast.net/~lang.dennis/code/ring/ring.html
+            //  Slightly modified for naming
+
+            template <class T, size_t RingSize>
+            class TSRingBuffer
+            {
+            public:
+                TSRingBuffer()
+                    : m_size(RingSize), m_buffer(new T[RingSize]), m_rIndex(0), m_wIndex(0)
+                { }
+
+                ~TSRingBuffer()
+                {
+                    delete [] m_buffer;
+                };
+
+                size_t next(size_t n) const
+                {
+                    return (n + 1) % m_size;
+                }
+
+                bool empty() const
+                {
+                    return (m_rIndex == m_wIndex);
+                }
+
+                bool full() const
+                {
+                    return (next(m_wIndex) == m_rIndex);
+                }
+
+                bool put(const T &value)
+                {
+                    if (full())
+                        return false;
+                    m_buffer[m_wIndex] = value;
+                    m_wIndex = next(m_wIndex);
+                    return true;
+                }
+
+                bool get(T &value)
+                {
+                    if (empty())
+                        return false;
+                    value = m_buffer[m_rIndex];
+                    m_rIndex = next(m_rIndex);
+                    return true;
+                }
+
+            private:
+                size_t          m_size;
+                T              *m_buffer;
+
+                // volatile is only used to keep compiler from placing values in registers.
+                // volatile does NOT make the index thread safe.
+                volatile size_t m_rIndex;
+                volatile size_t m_wIndex;
+            };
+
+        void copy_block(Block *block);
+
         float frequency;
         uint32_t period;
         std::array<StepperMotor*, k_max_actuators> motor;
@@ -59,7 +124,8 @@ class StepTicker{
             uint32_t total_move_ticks;
         };
         block_info_t block_info;
-        Block *next_block{nullptr};
+
+        TSRingBuffer<Block*, 4> jobq;
 
         // this is the data needed to determine when each motor needs to be issued a step
         struct tickinfo_t {
index 1aa5907..d3c435c 100644 (file)
@@ -37,10 +37,6 @@ void StepperMotor::init()
 {
     // register this motor with the step ticker, and get its index in that array and bit position
     this->index= THEKERNEL->step_ticker->register_motor(this);
-    this->moving = false;
-    this->stepped = 0;
-    this->is_move_finished = false;
-    this->force_finish= false;
 
     steps_per_mm         = 1.0F;
     max_rate             = 50.0F;
@@ -50,18 +46,6 @@ void StepperMotor::init()
     current_position_steps= 0;
 }
 
-// // Instruct the StepperMotor to move a certain number of steps
-// StepperMotor* StepperMotor::move( bool direction, unsigned int steps, float initial_speed)
-// {
-//     set_direction(direction);
-//     this->direction = direction;
-//     this->force_finish= false;
-
-//     // Zero our tool counters
-//     this->stepped = 0;
-//     return this;
-// }
-
 void StepperMotor::change_steps_per_mm(float new_steps)
 {
     steps_per_mm = new_steps;
index 44efa6a..38a315f 100644 (file)
@@ -5,8 +5,7 @@
       You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
 */
 
-#ifndef STEPPERMOTOR_H
-#define STEPPERMOTOR_H
+#pragma once
 
 #include "Pin.h"
 #include <atomic>
@@ -27,11 +26,7 @@ class StepperMotor {
 
         inline void enable(bool state) { en_pin.set(!state); };
 
-        bool is_moving() const { return moving; }
         bool which_direction() const { return direction; }
-//        void move_finished();
-//        StepperMotor* move( bool direction, unsigned int steps, float initial_speed= -1.0F);
-//        StepperMotor* set_speed( float speed );
 
         float get_steps_per_second()  const { return steps_per_second; }
         float get_steps_per_mm()  const { return steps_per_mm; }
@@ -43,8 +38,6 @@ class StepperMotor {
         void set_max_rate(float mr) { max_rate= mr; }
 
         int  steps_to_target(float);
-        uint32_t get_stepped() const { return stepped; }
-        void force_finish_move() { force_finish= true; }
 
         friend class StepTicker;
         friend class Stepper;
@@ -70,14 +63,8 @@ class StepperMotor {
         int32_t last_milestone_steps;
         float   last_milestone_mm;
 
-        uint32_t stepped; // TBD may not be needed
         volatile struct {
-            volatile bool is_move_finished:1; // Whether the move just finished
-            volatile bool moving:1;
-            volatile bool force_finish:1; // set to force a move to finish early
             bool direction:1;
         };
 };
 
-#endif
-
index 3f20edd..041e0a5 100644 (file)
@@ -120,11 +120,7 @@ void Stepper::on_block_begin(void *argument)
     this->current_block = block;
 
     // setup stepticker to execute this block
-    // if it is running then add this to next block otherwise it needs to be started
-    // if(!THEKERNEL->step_ticker->is_next_block()) {
-
-    // }
-    THEKERNEL->step_ticker->copy_block(block);
+    THEKERNEL->step_ticker->add_job(block);
 }
 
 // Current block is discarded
index 7ee2754..652a9bf 100644 (file)
@@ -37,7 +37,7 @@
 #include "ConfigValue.h"
 #include "Config.h"
 #include "checksumm.h"
-
+#include "StepTicker.h"
 
 #define motor_driver_control_checksum  CHECKSUM("motor_driver_control")
 #define sense_resistor_checksum        CHECKSUM("sense_resistor")
@@ -896,10 +896,10 @@ void TMC26X::dumpStatus(StreamOutput *stream, bool readable)
 
     } else {
         // TODO hardcoded for X need to select ABC as needed
-        bool moving = THEKERNEL->robot->actuators[0]->is_moving();
+        bool moving = THEKERNEL->step_ticker->is_moving(0);
         // dump out in the format that the processing script needs
         if (moving) {
-            stream->printf("#sg%d,p%lu,k%u,r,", getCurrentStallGuardReading(), THEKERNEL->robot->actuators[0]->get_stepped(), getCoolstepCurrent());
+            stream->printf("#sg%d,p%lu,k%u,r,", getCurrentStallGuardReading(), THEKERNEL->step_ticker->get_stepped(0), getCoolstepCurrent());
         } else {
             readStatus(TMC26X_READOUT_POSITION); // get the status bits
             stream->printf("#s,");