Browse Source

Use uint8_t consistently for the block buffer's index

Instead of using a mixture of int8_t, unsigned char and (incorrectly)
int, use uint8_t consistently for indexing the current block.

This improves the performance of the wait loop in plan_buffer_line,
which currently expands all comparisons to a word for no reason.

This also extends the theoretical limit to 128 entries.
Add some static assertions to ensure BLOCK_BUFFER_SIZE is correct.
Yuri D'Elia 2 years ago
parent
commit
79287ffb3d
2 changed files with 22 additions and 18 deletions
  1. 13 13
      Firmware/planner.cpp
  2. 9 5
      Firmware/planner.h

+ 13 - 13
Firmware/planner.cpp

@@ -109,9 +109,9 @@ unsigned char g_uc_extruder_last_move[3] = {0,0,0};
 //===========================================================================
 //=================semi-private variables, used in inline  functions    =====
 //===========================================================================
-block_t block_buffer[BLOCK_BUFFER_SIZE];            // A ring buffer for motion instfructions
-volatile unsigned char block_buffer_head;           // Index of the next block to be pushed
-volatile unsigned char block_buffer_tail;           // Index of the block to process now
+block_t block_buffer[BLOCK_BUFFER_SIZE];    // A ring buffer for motion instfructions
+volatile uint8_t block_buffer_head;         // Index of the next block to be pushed
+volatile uint8_t block_buffer_tail;         // Index of the block to process now
 
 #ifdef PLANNER_DIAGNOSTICS
 // Diagnostic function: Minimum number of planned moves since the last 
@@ -136,17 +136,17 @@ static bool plan_reset_next_e_sched;
 
 // Returns the index of the next block in the ring buffer
 // NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication.
-static inline int8_t next_block_index(int8_t block_index) {
+static inline uint8_t next_block_index(uint8_t block_index) {
   if (++ block_index == BLOCK_BUFFER_SIZE)
-    block_index = 0; 
+    block_index = 0;
   return block_index;
 }
 
 
 // Returns the index of the previous block in the ring buffer
-static inline int8_t prev_block_index(int8_t block_index) {
+static inline uint8_t prev_block_index(uint8_t block_index) {
   if (block_index == 0)
-    block_index = BLOCK_BUFFER_SIZE; 
+    block_index = BLOCK_BUFFER_SIZE;
   -- block_index;
   return block_index;
 }
@@ -358,14 +358,14 @@ void planner_recalculate(const float &safe_final_speed)
     // Reverse pass
     // Make a local copy of block_buffer_tail, because the interrupt can alter it
     // by consuming the blocks, therefore shortening the queue.
-    unsigned char tail = block_buffer_tail;
+    uint8_t tail = block_buffer_tail;
     uint8_t block_index;
     block_t *prev, *current, *next;
 
 //    SERIAL_ECHOLNPGM("planner_recalculate - 1");
 
     // At least three blocks are in the queue?
-    unsigned char n_blocks = (block_buffer_head + BLOCK_BUFFER_SIZE - tail) & (BLOCK_BUFFER_SIZE - 1);
+    uint8_t n_blocks = (block_buffer_head + BLOCK_BUFFER_SIZE - tail) & (BLOCK_BUFFER_SIZE - 1);
     if (n_blocks >= 3) {
         // Initialize the last tripple of blocks.
         block_index = prev_block_index(block_buffer_head);
@@ -709,7 +709,7 @@ float junction_deviation = 0.1;
 void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, uint8_t extruder, const float* gcode_target)
 {
     // Calculate the buffer head after we push this byte
-  int next_buffer_head = next_block_index(block_buffer_head);
+  uint8_t next_buffer_head = next_block_index(block_buffer_head);
 
   // If the buffer is full: good! That means we are well ahead of the robot. 
   // Rest here until there is room in the buffer.
@@ -1475,7 +1475,7 @@ void update_mode_profile()
 }
 #endif //TMC2130
 
-unsigned char number_of_blocks()
+uint8_t number_of_blocks()
 {
 	return (block_buffer_head + BLOCK_BUFFER_SIZE - block_buffer_tail) & (BLOCK_BUFFER_SIZE - 1);
 }
@@ -1505,8 +1505,8 @@ void planner_add_sd_length(uint16_t sdlen)
 
 uint16_t planner_calc_sd_length()
 {
-	unsigned char _block_buffer_head = block_buffer_head;
-	unsigned char _block_buffer_tail = block_buffer_tail;
+	uint8_t _block_buffer_head = block_buffer_head;
+	uint8_t _block_buffer_tail = block_buffer_tail;
 	uint16_t sdlen = 0;
 	while (_block_buffer_head != _block_buffer_tail)
 	{

+ 9 - 5
Firmware/planner.h

@@ -202,16 +202,20 @@ extern uint8_t maxlimit_status;
     extern float autotemp_factor;
 #endif
 
-    
 
+// Check for BLOCK_BUFFER_SIZE requirements
+static_assert(!(BLOCK_BUFFER_SIZE & (BLOCK_BUFFER_SIZE - 1)),
+              "BLOCK_BUFFER_SIZE must be a power of two");
+static_assert(BLOCK_BUFFER_SIZE <= (UINT8_MAX>>1),
+              "BLOCK_BUFFER_SIZE too large for uint8_t");
 
 extern block_t block_buffer[BLOCK_BUFFER_SIZE];            // A ring buffer for motion instfructions
 // Index of the next block to be pushed into the planner queue.
-extern volatile unsigned char block_buffer_head;
+extern volatile uint8_t block_buffer_head;
 // Index of the first block in the planner queue.
 // This is the block, which is being currently processed by the stepper routine, 
 // or which is first to be processed by the stepper routine.
-extern volatile unsigned char block_buffer_tail; 
+extern volatile uint8_t block_buffer_tail;
 // Called when the current block is no longer needed. Discards the block and makes the memory
 // available for new blocks.    
 FORCE_INLINE void plan_discard_current_block()  
@@ -246,7 +250,7 @@ FORCE_INLINE uint8_t moves_planned() {
 }
 
 FORCE_INLINE bool planner_queue_full() {
-    unsigned char next_block_index = block_buffer_head;
+    uint8_t next_block_index = block_buffer_head;
     if (++ next_block_index == BLOCK_BUFFER_SIZE)
         next_block_index = 0; 
     return block_buffer_tail == next_block_index;
@@ -267,7 +271,7 @@ void reset_acceleration_rates();
 
 void update_mode_profile();
 
-unsigned char number_of_blocks();
+uint8_t number_of_blocks();
 
 // #define PLANNER_DIAGNOSTICS
 #ifdef PLANNER_DIAGNOSTICS