Commit | Line | Data |
---|---|---|
f80d18b9 L |
1 | /* |
2 | This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl) with additions from Sungeun K. Jeon (https://github.com/chamnit/grbl) | |
3 | Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. | |
4 | Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
5 | You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. | |
6 | */ | |
7 | ||
8 | using namespace std; | |
9 | #include <vector> | |
10 | #include "libs/nuts_bolts.h" | |
11 | #include "libs/RingBuffer.h" | |
12 | #include "../communication/utils/Gcode.h" | |
13 | #include "libs/Module.h" | |
14 | #include "libs/Kernel.h" | |
15 | #include "Timer.h" // mbed.h lib | |
16 | #include "wait_api.h" // mbed.h lib | |
17 | #include "Block.h" | |
18 | #include "Conveyor.h" | |
19 | #include "Planner.h" | |
20 | ||
edac9072 AW |
21 | // The conveyor holds the queue of blocks, takes care of creating them, and starting the executing chain of blocks |
22 | ||
f80d18b9 L |
23 | Conveyor::Conveyor(){ |
24 | this->current_block = NULL; | |
25 | this->looking_for_new_block = false; | |
5bd37b4d MM |
26 | queue.resize(32); |
27 | gc_pending = queue.tail_i; | |
702023f3 MM |
28 | } |
29 | ||
d149c730 | 30 | void Conveyor::on_module_loaded(){ |
702023f3 MM |
31 | register_for_event(ON_IDLE); |
32 | } | |
33 | ||
edac9072 | 34 | // Delete blocks here, because they can't be deleted in interrupt context ( see Block.cpp:release ) |
d149c730 | 35 | void Conveyor::on_idle(void* argument){ |
5bd37b4d MM |
36 | while (queue.tail_i != gc_pending) |
37 | { | |
6bb45cd1 | 38 | // Cleanly delete block |
5bd37b4d | 39 | Block* block = queue.tail_ref(); |
6bb45cd1 | 40 | block->gcodes.clear(); |
5bd37b4d | 41 | queue.consume_tail(); |
702023f3 | 42 | } |
f80d18b9 L |
43 | } |
44 | ||
e0ee24ed MM |
45 | void Conveyor::append_gcode(Gcode* gcode) |
46 | { | |
47 | gcode->mark_as_taken(); | |
5bd37b4d | 48 | if (queue.is_empty()) |
e0ee24ed MM |
49 | THEKERNEL->call_event(ON_GCODE_EXECUTE, gcode); |
50 | else | |
5bd37b4d | 51 | queue.head_ref()->append_gcode(gcode); |
e0ee24ed MM |
52 | } |
53 | ||
f80d18b9 L |
54 | // Append a block to the list |
55 | Block* Conveyor::new_block(){ | |
56 | ||
f80d18b9 | 57 | // Take the next untaken block on the queue ( the one after the last one ) |
5bd37b4d | 58 | Block* block = this->queue.head_ref(); |
f80d18b9 | 59 | // Then clean it up |
1cf31736 | 60 | block->clear(); |
702023f3 | 61 | |
f80d18b9 L |
62 | block->initial_rate = -2; |
63 | block->final_rate = -2; | |
1cf31736 JM |
64 | |
65 | // Create a new virgin Block in the queue | |
5bd37b4d | 66 | queue.produce_head(); |
6bb45cd1 | 67 | |
f80d18b9 L |
68 | return block; |
69 | } | |
70 | ||
71 | // Used by blocks to signal when they are ready to be used by the system | |
72 | void Conveyor::new_block_added(){ | |
73 | if( this->current_block == NULL ){ | |
74 | this->pop_and_process_new_block(33); | |
75 | } | |
76 | } | |
77 | ||
78 | // Process a new block in the queue | |
79 | void Conveyor::pop_and_process_new_block(int debug){ | |
80 | if( this->looking_for_new_block ){ return; } | |
81 | this->looking_for_new_block = true; | |
82 | ||
83 | if( this->current_block != NULL ){ this->looking_for_new_block = false; return; } | |
84 | ||
85 | // Return if queue is empty | |
5bd37b4d | 86 | if( queue.is_empty() ){ |
f80d18b9 L |
87 | this->current_block = NULL; |
88 | // TODO : ON_QUEUE_EMPTY event | |
89 | this->looking_for_new_block = false; | |
90 | return; | |
91 | } | |
702023f3 | 92 | |
f80d18b9 | 93 | // Get a new block |
5bd37b4d | 94 | this->current_block = this->queue.tail_ref(); |
f80d18b9 L |
95 | |
96 | // Tell all modules about it | |
314ab8f7 | 97 | THEKERNEL->call_event(ON_BLOCK_BEGIN, this->current_block); |
702023f3 | 98 | |
35089dc7 | 99 | // In case the module was not taken |
f80d18b9 | 100 | if( this->current_block->times_taken < 1 ){ |
6bb45cd1 JM |
101 | Block* temp = this->current_block; |
102 | this->current_block = NULL; // It seems this was missing and adding it fixes things, if something breaks, this may be a suspect | |
103 | temp->take(); | |
12800c08 | 104 | temp->release(); |
f80d18b9 L |
105 | } |
106 | ||
107 | this->looking_for_new_block = false; | |
108 | ||
109 | } | |
110 | ||
edac9072 | 111 | // Wait for the queue to have a given number of free blocks |
5bd37b4d MM |
112 | void Conveyor::wait_for_queue(int free_blocks) |
113 | { | |
114 | while (queue.is_full()) | |
314ab8f7 | 115 | THEKERNEL->call_event(ON_IDLE); |
f80d18b9 | 116 | } |
17c68379 | 117 | |
edac9072 | 118 | // Wait for the queue to be empty |
5bd37b4d MM |
119 | void Conveyor::wait_for_empty_queue() |
120 | { | |
121 | while (!queue.is_empty()) | |
314ab8f7 | 122 | THEKERNEL->call_event(ON_IDLE); |
17c68379 BG |
123 | } |
124 | ||
68d16168 | 125 | // Return true if the queue is empty |
5bd37b4d MM |
126 | bool Conveyor::is_queue_empty() |
127 | { | |
128 | return queue.is_empty(); | |
68d16168 L |
129 | } |
130 | ||
5bd37b4d MM |
131 | |
132 | // feels hacky, but apparently the way to do it | |
133 | #include "HeapRing.cpp" | |
134 | template class HeapRing<Block>; |