| 155 | } |
| 156 | |
| 157 | bool DDARing::CanAddMove() const noexcept |
| 158 | { |
| 159 | // We have two constraints here that may prevent us from using the last free element in the ring: |
| 160 | // 1. DDA::Prepare needs to access the previous DDA in the ring to find the endpoints of the previous move. |
| 161 | // So we must not allocate an empty slot if the next one has state 'provisional'. |
| 162 | // 2. If all DDAs in the ring have state 'committed' then function ManageIOBitsAndFeedforward may loop indefinitely. |
| 163 | // So we must not allocate an empty slot if the next one has state 'committed'. |
| 164 | // The simplest solution is not to allow the last free slot to be allocated. |
| 165 | if ( addPointer->GetState() == DDA::empty |
| 166 | && addPointer->GetNext()->GetState() == DDA::empty |
| 167 | ) |
| 168 | { |
| 169 | // In order to react faster to speed and extrusion rate changes, only add more moves if the total duration of |
| 170 | // all un-frozen moves is less than 2 seconds, or the total duration of all but the first un-frozen move is less than 0.5 seconds. |
| 171 | const DDA *dda = addPointer; |
| 172 | uint32_t unPreparedTime = 0; |
| 173 | uint32_t prevMoveTime = 0; |
| 174 | for(;;) |
| 175 | { |
| 176 | dda = dda->GetPrevious(); |
| 177 | if (dda->GetState() != DDA::provisional) |
| 178 | { |
| 179 | break; |
| 180 | } |
| 181 | unPreparedTime += prevMoveTime; |
| 182 | prevMoveTime = dda->GetClocksNeeded(); |
| 183 | } |
| 184 | |
| 185 | return (unPreparedTime < StepClockRate/2 || unPreparedTime + prevMoveTime < 2 * StepClockRate); |
| 186 | } |
| 187 | return false; |
| 188 | } |
| 189 | |
| 190 | // Add a new move, returning true if it represents real movement |
| 191 | MovementError DDARing::AddStandardMove(const RawMove &nextMove, bool doMotorMapping) noexcept |
no test coverage detected