Reads a complete rotation of the disk, and returns it using the callback function which can return FALSE to stop An instance of RotationExtractor is required. This is purely to save on re-allocations. It is internally reset each time
| 1351 | // Reads a complete rotation of the disk, and returns it using the callback function which can return FALSE to stop |
| 1352 | // An instance of RotationExtractor is required. This is purely to save on re-allocations. It is internally reset each time |
| 1353 | DiagnosticResponse ArduinoInterface::readRotation(MFMExtractionTarget& extractor, const unsigned int maxOutputSize, RotationExtractor::MFMSample* firstOutputBuffer, RotationExtractor::IndexSequenceMarker& startBitPatterns, std::function<bool(RotationExtractor::MFMSample** mfmData, const unsigned int dataLengthInBits)> onRotation, bool useHalfPLL) { |
| 1354 | m_lastCommand = LastCommand::lcReadTrackStream; |
| 1355 | |
| 1356 | if (m_version.major == 1 && m_version.minor < 8) { |
| 1357 | m_lastError = DiagnosticResponse::drOldFirmware; |
| 1358 | return m_lastError; |
| 1359 | } |
| 1360 | |
| 1361 | // Who would do this, right? |
| 1362 | if (maxOutputSize < 1 || !firstOutputBuffer) { |
| 1363 | m_lastError = DiagnosticResponse::drError; |
| 1364 | return m_lastError; |
| 1365 | } |
| 1366 | |
| 1367 | const bool highPrecisionMode = !m_isHDMode && m_version.deviceFlags1 & FLAGS_HIGH_PRECISION_SUPPORT; |
| 1368 | char mode = highPrecisionMode ? COMMAND_READTRACKSTREAM_HIGHPRECISION : COMMAND_READTRACKSTREAM; |
| 1369 | |
| 1370 | if (mode == COMMAND_READTRACKSTREAM_HIGHPRECISION && m_version.deviceFlags1 & FLAGS_FLUX_READ && useHalfPLL) mode = COMMAND_READTRACKSTREAM_HALFPLL; |
| 1371 | |
| 1372 | |
| 1373 | m_lastError = runCommand(mode); |
| 1374 | |
| 1375 | if (m_lastError != DiagnosticResponse::drOK) return m_lastError; |
| 1376 | |
| 1377 | m_isStreaming = true; |
| 1378 | |
| 1379 | |
| 1380 | #ifdef USE_THREADDED_READER |
| 1381 | std::mutex safetyLock; |
| 1382 | // I was using a deque, but its much faster to just keep switching between two vectors |
| 1383 | std::vector<unsigned char> readBuffer; |
| 1384 | readBuffer.reserve(4096); |
| 1385 | std::vector<unsigned char> tempReadBuffer; |
| 1386 | tempReadBuffer.reserve(4096); |
| 1387 | #ifdef _WIN32 |
| 1388 | m_comPort.setReadTimeouts(100, 0); // match linux |
| 1389 | #endif |
| 1390 | std::thread* backgroundReader = new std::thread([this, &readBuffer, &safetyLock]() { |
| 1391 | #ifdef _WIN32 |
| 1392 | SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); |
| 1393 | #endif |
| 1394 | unsigned char buffer[1024]; // the LINUX serial buffer is only 512 bytes anyway |
| 1395 | while (m_isStreaming) { |
| 1396 | uint32_t waiting = m_comPort.justRead(buffer, 1024); |
| 1397 | if (waiting>0) { |
| 1398 | safetyLock.lock(); |
| 1399 | readBuffer.insert(readBuffer.end(), buffer, buffer+waiting); |
| 1400 | safetyLock.unlock(); |
| 1401 | } else |
| 1402 | std::this_thread::sleep_for(std::chrono::microseconds(200)); |
| 1403 | } |
| 1404 | }); |
| 1405 | |
| 1406 | |
| 1407 | #else |
| 1408 | applyCommTimeouts(true); |
| 1409 | unsigned char tempReadBuffer[2048] = { 0 }; |
| 1410 | #endif |
no test coverage detected