void LX::CommandModeQuick(Port &port, OperationEnvironment &env) { port.Write(SYN); env.Sleep(500); port.Write(SYN); env.Sleep(500); port.Write(SYN); env.Sleep(500); }
void LX::CommandModeQuick(Port &port, OperationEnvironment &env) { SendSYN(port); env.Sleep(500); SendSYN(port); env.Sleep(500); SendSYN(port); env.Sleep(500); }
void LX::CommandModeQuick(Port &port, OperationEnvironment &env) { SendSYN(port); env.Sleep(std::chrono::milliseconds(500)); SendSYN(port); env.Sleep(std::chrono::milliseconds(500)); SendSYN(port); env.Sleep(std::chrono::milliseconds(500)); }
bool Volkslogger::SendCommand(Port &port, OperationEnvironment &env, Command cmd, uint8_t param1, uint8_t param2) { static constexpr unsigned delay = 2; /* flush buffers */ if (!port.FullFlush(env, 20, 100)) return false; /* reset command interpreter */ if (!Reset(port, env, 6)) return false; /* send command packet */ const uint8_t cmdarray[8] = { (uint8_t)cmd, param1, param2, 0, 0, 0, 0, 0, }; if (!port.Write(ENQ)) return false; env.Sleep(delay); if (!SendWithCRC(port, cmdarray, sizeof(cmdarray), env)) return false; /* wait for confirmation */ return port.WaitRead(env, 4000) == Port::WaitResult::READY && port.GetChar() == 0; }
int Volkslogger::SendCommandReadBulk(Port &port, unsigned baud_rate, OperationEnvironment &env, Command cmd, uint8_t param1, void *buffer, size_t max_length, const unsigned timeout_firstchar_ms) { unsigned old_baud_rate = port.GetBaudrate(); if (old_baud_rate != 0) { if (!SendCommandSwitchBaudRate(port, env, cmd, param1, baud_rate)) return -1; /* after switching baud rates, this sleep time is necessary; it has been verified experimentally */ env.Sleep(300); } else { /* port does not support baud rate switching, use plain SendCommand() without new baud rate */ if (!SendCommand(port, env, cmd, param1)) return -1; } int nbytes = ReadBulk(port, env, buffer, max_length, timeout_firstchar_ms); if (old_baud_rate != 0) port.SetBaudrate(old_baud_rate); return nbytes; }
bool Volkslogger::WriteBulk(Port &port, OperationEnvironment &env, const void *buffer, unsigned length) { const unsigned delay = 1; env.SetProgressRange(length); uint16_t crc16 = 0; const uint8_t *p = (const uint8_t *)buffer, *end = p + length; while (p < end) { unsigned n = end - p; if (n > 400) n = 400; n = port.Write(p, n); if (n == 0) return false; crc16 = UpdateCRC16CCITT(p, n, crc16); p += n; env.SetProgressPosition(p - (const uint8_t *)buffer); /* throttle sending a bit, or the Volkslogger's receive buffer will overrun */ env.Sleep(delay * 100); } return port.Write(crc16 >> 8) && port.Write(crc16 & 0xff); }
virtual void Run(OperationEnvironment &env) { env.SetText(_T("Working...")); env.SetProgressRange(30); for (unsigned i = 0; i < 30 && !env.IsCancelled(); ++i) { env.SetProgressPosition(i); env.Sleep(500); } }
bool Port::WaitConnected(OperationEnvironment &env) { while (GetState() == PortState::LIMBO && !env.IsCancelled()) env.Sleep(200); return GetState() == PortState::READY; }
bool LXDevice::EnableCommandMode(OperationEnvironment &env) { { ScopeLock protect(mutex); if (mode == Mode::COMMAND) return true; } port.StopRxThread(); if (!EnablePassThrough(env)) { mode = Mode::UNKNOWN; return false; } /* make sure the pass-through command has been sent to the device before we continue sending commands */ port.Drain(); if (bulk_baud_rate != 0) { old_baud_rate = port.GetBaudrate(); if (old_baud_rate == bulk_baud_rate) old_baud_rate = 0; else if (old_baud_rate != 0) { /* before changing the baud rate, we need an additional delay, because Port::Drain() does not seem to work reliably on Linux with a USB-RS232 converter; with a V7+Nano, 100ms is more than enough */ env.Sleep(100); if (!port.SetBaudrate(bulk_baud_rate)) { mode = Mode::UNKNOWN; return false; } } } else old_baud_rate = 0; if (!LX::CommandMode(port, env)) { if (old_baud_rate != 0) { port.SetBaudrate(old_baud_rate); old_baud_rate = 0; } ScopeLock protect(mutex); mode = Mode::UNKNOWN; return false; } busy = false; ScopeLock protect(mutex); mode = Mode::COMMAND; return true; }
bool Volkslogger::SendCommandWriteBulk(Port &port, OperationEnvironment &env, Command cmd, const void *data, size_t size) { if (!SendCommand(port, env, cmd, 0, 0) || !WaitForACK(port, env)) return false; env.Sleep(100); return WriteBulk(port, env, data, size) && WaitForACK(port, env); }
bool DeviceDescriptor::DoOpen(OperationEnvironment &env) { assert(config.IsAvailable()); if (config.port_type == DeviceConfig::PortType::INTERNAL) return OpenInternalSensors(); if (config.port_type == DeviceConfig::PortType::DROIDSOAR_V2) return OpenDroidSoarV2(); if (config.port_type == DeviceConfig::PortType::I2CPRESSURESENSOR) return OpenI2Cbaro(); if (config.port_type == DeviceConfig::PortType::NUNCHUCK) return OpenNunchuck(); if (config.port_type == DeviceConfig::PortType::IOIOVOLTAGE) return OpenVoltage(); if (config.port_type == DeviceConfig::PortType::ADCAIRSPEED) return OpenAdcAirspeed(); reopen_clock.Update(); Port *port = OpenPort(config, *this); if (port == NULL) { TCHAR name_buffer[64]; const TCHAR *name = config.GetPortName(name_buffer, 64); StaticString<256> msg; msg.Format(_T("%s: %s."), _("Unable to open port"), name); env.SetErrorMessage(msg); return false; } while (port->GetState() == PortState::LIMBO) { env.Sleep(200); if (env.IsCancelled() || port->GetState() == PortState::FAILED) { delete port; return false; } } if (!Open(*port, env)) { delete port; return false; } return true; }
bool CAI302Device::SetBaudRate(unsigned baud_rate, OperationEnvironment &env) { if (!CommandMode(env) || !CAI302::SetBaudRate(port, baud_rate, env) || !port.Drain()) return false; /* the CAI302 needs some time to apply the new baud rate; if we switch too early, it'll cancel the command */ env.Sleep(500); return port.SetBaudrate(baud_rate) && CAI302::CommandMode(port, env); }
bool CaiGpsNavDevice::Open(OperationEnvironment &env) { port->Write(CtrlC); env.Sleep(50); port->Write("NMEA\r"); // This is for a slightly different mode, that // apparently outputs pressure info too... //port->Write("PNP\r\n"); //port->Write("LOG 0\r\n"); return true; }
bool Volkslogger::Reset(Port &port, OperationEnvironment &env, unsigned n) { static constexpr unsigned delay = 2; while (n-- > 0) { if (!port.Write(CAN)) return false; env.Sleep(delay); } return true; }
bool Volkslogger::Reset(Port &port, OperationEnvironment &env, unsigned n) { static constexpr auto delay = std::chrono::milliseconds(2); while (n-- > 0) { if (!port.Write(CAN)) return false; env.Sleep(delay); } return true; }
size_t Volkslogger::ReadFlight(Port &port, unsigned databaud, OperationEnvironment &env, unsigned flightnr, bool secmode, void *buffer, size_t buffersize) { const Volkslogger::Command cmd = secmode ? Volkslogger::cmd_GFS : Volkslogger::cmd_GFL; /* * It is necessary to wait long for the first reply from * the Logger in ReadBulk. * Since the VL needs time to calculate the Security of * the log before it responds. */ const unsigned timeout_firstchar_ms = 600000; // Download binary log data supports BulkBaudrate int groesse = SendCommandReadBulk(port, databaud, env, cmd, flightnr, buffer, buffersize, timeout_firstchar_ms); if (groesse <= 0) return 0; // read signature env.Sleep(300); /* * Testing has shown that downloading the Signature does not support * BulkRate. It has to be done with standard IO Rate (9600) */ int sgr = SendCommandReadBulk(port, env, Volkslogger::cmd_SIG, (uint8_t *)buffer + groesse, buffersize - groesse); if (sgr <= 0) return 0; return groesse + sgr; }
bool EWDevice::DeclareInner(const struct Declaration &declaration, OperationEnvironment &env) { char sTmp[72]; ewDecelTpIndex = 0; if (!TryConnect(env)) return false; // send SetPilotInfo WriteWithChecksum(port, "#SPI"); env.Sleep(50); char sPilot[13], sGliderType[9], sGliderID[9]; convert_string(sPilot, sizeof(sPilot), declaration.pilot_name); convert_string(sGliderType, sizeof(sGliderType), declaration.aircraft_type); convert_string(sGliderID, sizeof(sGliderID), declaration.aircraft_registration); // build string (field 4-5 are GPS info, no idea what to write) sprintf(sTmp, "%-12s%-8s%-8s%-12s%-12s%-6s\r", sPilot, sGliderType, sGliderID, "" /* GPS Model */, "" /* GPS Serial No. */, "" /* Flight Date */ /* format unknown, left blank (GPS has a RTC) */); port.Write(sTmp); if (!port.ExpectString("OK\r", env)) return false; /* sprintf(sTmp, "#SUI%02d", 0); // send pilot name WriteWithChecksum(port, sTmp); env.Sleep(50); port.Write(PilotsName); port.Write('\r'); if (!port.ExpectString("OK\r")) return false; sprintf(sTmp, "#SUI%02d", 1); // send type of aircraft WriteWithChecksum(port, sTmp); env.Sleep(50); port.Write(Class); port.Write('\r'); if (!port.ExpectString("OK\r")) nDeclErrorCode = 1; sprintf(sTmp, "#SUI%02d", 2); // send aircraft ID WriteWithChecksum(port, sTmp); env.Sleep(50); port.Write(ID); port.Write('\r'); if (!port.ExpectString("OK\r")) return false; */ // clear all 6 TP's for (int i = 0; i < 6; i++) { sprintf(sTmp, "#CTP%02d", i); WriteWithChecksum(port, sTmp); if (!port.ExpectString("OK\r", env)) return false; } for (unsigned j = 0; j < declaration.Size(); ++j) if (!AddWaypoint(declaration.GetWaypoint(j), env)) return false; return true; }
bool EWDevice::DeclareInner(const struct Declaration *decl, OperationEnvironment &env) { char sTmp[72]; ewDecelTpIndex = 0; if (!TryConnect()) return false; WriteWithChecksum(port, "#SPI"); // send SetPilotInfo env.Sleep(50); char sPilot[13], sGliderType[9], sGliderID[9]; convert_string(sPilot, sizeof(sPilot), decl->PilotName); convert_string(sGliderType, sizeof(sGliderType), decl->AircraftType); convert_string(sGliderID, sizeof(sGliderID), decl->AircraftReg); // build string (field 4-5 are GPS info, no idea what to write) sprintf(sTmp, "%-12s%-8s%-8s%-12s%-12s%-6s\r", sPilot, sGliderType, sGliderID, "", // GPS Model "", // GPS Serial No. "" // Flight Date, // format unknown, // left blank (GPS // has a RTC) ); port->Write(sTmp); if (!port->ExpectString("OK\r")) return false; /* sprintf(sTmp, "#SUI%02d", 0); // send pilot name WriteWithChecksum(port, sTmp); env.Sleep(50); port->Write(PilotsName); port->Write('\r'); if (!port->ExpectString("OK\r")) return false; sprintf(sTmp, "#SUI%02d", 1); // send type of aircraft WriteWithChecksum(port, sTmp); env.Sleep(50); port->Write(Class); port->Write('\r'); if (!port->ExpectString("OK\r")) nDeclErrorCode = 1; sprintf(sTmp, "#SUI%02d", 2); // send aircraft ID WriteWithChecksum(port, sTmp); env.Sleep(50); port->Write(ID); port->Write('\r'); if (!port->ExpectString("OK\r")) return false; */ for (int i=0; i<6; i++){ // clear all 6 TP's sprintf(sTmp, "#CTP%02d", i); WriteWithChecksum(port, sTmp); if (!port->ExpectString("OK\r")) return false; } for (unsigned j = 0; j < decl->size(); ++j) if (!AddWayPoint(decl->get_waypoint(j))) return false; return true; }
int Volkslogger::ReadBulk(Port &port, OperationEnvironment &env, void *buffer, size_t max_length, unsigned timeout_firstchar_ms) { unsigned nbytes = 0; bool dle_r = false; uint16_t crc16 = 0; bool start = false, ende = false; memset(buffer, 0xff, max_length); uint8_t *p = (uint8_t *)buffer; constexpr unsigned TIMEOUT_NORMAL_MS = 2000; /** * We need to wait longer for the first char to * give the logger time to calculate security * when downloading a log-file. * Therefore timeout_firstchar is configurable. * If the timeout parameter is not specified or 0, * set standard timeout */ if (timeout_firstchar_ms == 0) timeout_firstchar_ms = TIMEOUT_NORMAL_MS; while (!ende) { // Zeichen anfordern und darauf warten if (!port.Write(ACK)) return -1; // Set longer timeout on first char unsigned timeout = start ? TIMEOUT_NORMAL_MS : timeout_firstchar_ms; if (port.WaitRead(env, timeout) != Port::WaitResult::READY) return -1; int ch = port.GetChar(); if (ch < 0) return -1; // dabei ist Benutzerabbruch jederzeit möglich if (env.IsCancelled()) { env.Sleep(10); port.Write(CAN); port.Write(CAN); port.Write(CAN); return -1; } // oder aber das empfangene Zeichen wird ausgewertet switch (ch) { case DLE: if (!dle_r) { //!DLE, DLE -> Achtung! dle_r = true; } else { // DLE, DLE -> DLE-Zeichen dle_r = false; if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } } break; case ETX: if (!dle_r) { //!DLE, ETX -> Zeichen if (start) { if(nbytes < max_length) { *p++ = ch; } nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); }; } else { if (start) { ende = true; // DLE, ETX -> Blockende dle_r = false; } } break; case STX: if (!dle_r) { //!DLE, STX -> Zeichen if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } } else { start = true; // DLE, STX -> Blockstart dle_r = false; crc16 = 0; } break; default: if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } break; } } env.Sleep(100); if (crc16 != 0) return -1; if (nbytes < 2) return 0; // CRC am Ende abschneiden return nbytes - 2; }