//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Converts TCHAR[] string into US-ASCII string with characters safe for /// writing to LX devices. /// /// Characters are converted into their most similar representation /// in ASCII. Nonconvertable characters are replaced by '?'. /// /// Output string will always be terminated by '\0'. /// /// @param input input string (must be terminated with '\0') /// @param outSize output buffer size /// @param output output buffer /// /// @retval true all characters copied /// @retval false some characters could not be copied due to buffer size /// //static bool DevLXNano::Wide2LxAscii(const TCHAR* input, int outSize, char* output) { if (outSize == 0) return(false); int res = unicode2usascii(input, output, outSize); // replace all non-ascii characters with '?' - LX Colibri is very sensitive // on non-ascii chars - the electronic seal can be broken // (unicode2usascii() should be enough, but to be sure that someone has not // incorrectly changed unicode2usascii()) output--; while (*++output != '\0') { if (*output < 32 || *output > 126) *output = '?'; } return(res >= 0); } // Wide2LxAscii()
/** * @brief Sends task declaration * * @param d Device handle * @param decl Task declaration data * @param errBufSize The size of the buffer for error string * @param errBuf The buffer for error string * * @return Operation status */ bool CDevIMI::DeclarationWrite(PDeviceDescriptor_t d, const Declaration_t &decl, unsigned errBufSize, TCHAR errBuf[]) { if(!_connected) { // LKTOKEN _@M1411_ = "Device not connected!" _sntprintf(errBuf, errBufSize, _T("%s"), gettext(_T("_@M1411_"))); return false; } TDeclaration imiDecl; memset(&imiDecl, 0, sizeof(imiDecl)); // idecl.date ignored - will be set by FR unicode2usascii(decl.PilotName, imiDecl.header.plt, sizeof(imiDecl.header.plt)); // decl.header.db1Year = year; decl.header.db1Month = month; decl.header.db1Day = day; unicode2usascii(decl.AircraftType, imiDecl.header.gty, sizeof(imiDecl.header.gty)); unicode2usascii(decl.AircraftRego, imiDecl.header.gid, sizeof(imiDecl.header.gid)); unicode2usascii(decl.CompetitionID, imiDecl.header.cid, sizeof(imiDecl.header.cid)); unicode2usascii(decl.CompetitionClass, imiDecl.header.ccl, sizeof(imiDecl.header.ccl)); // strncpy(decl.header.clb, idecl.clb, sizeof(decl.header.clb)); // strncpy(decl.header.sit, idecl.sit, sizeof(decl.header.sit)); // strncpy(decl.header.cm2, idecl.cm2, sizeof(decl.header.cm2)); // decl.header.db2Year = year; decl.header.db2Month = month; decl.header.db2Day = day; TCHAR tskName[IMIDECL_TASK_NAME_LENGTH]; TaskFileName(IMIDECL_TASK_NAME_LENGTH, tskName); unicode2usascii(tskName, imiDecl.header.tskName, sizeof(imiDecl.header.tskName)); // decl.header.tskYear = year; decl.header.tskMonth = month; decl.header.tskDay = day; // decl.header.tskNumber = MIN(9999, idecl.tskNumber); IMIWaypoint(decl, 0, imiDecl.wp[0]); for(int i=0; i<decl.num_waypoints; i++) IMIWaypoint(decl, i + 1, imiDecl.wp[i + 1]); IMIWaypoint(decl, decl.num_waypoints + 1, imiDecl.wp[decl.num_waypoints + 1]); // send declaration for current task const TMsg *msg = SendRet(d, errBufSize, errBuf, MSG_DECLARATION, &imiDecl, sizeof(imiDecl), MSG_ACK_SUCCESS, 0, static_cast<IMIBYTE>(-1)); if(!msg && errBuf[0] == '\0') { // LKTOKEN _@M1415_ = "Declaration not accepted!" _sntprintf(errBuf, errBufSize, _T("%s"), gettext(_T("_@M1415_"))); } return msg; }
/** * @brief Sets data in IMI Waypoint structure * * @param decl LK task declaration * @param imiIdx The index of IMI waypoint to set * @param imiWp IMI waypoint structure to set */ void CDevIMI::IMIWaypoint(const Declaration_t &decl, unsigned imiIdx, TWaypoint &imiWp) { unsigned idx = imiIdx == 0 ? 0 : (imiIdx == (unsigned)decl.num_waypoints + 1 ? imiIdx - 2 : imiIdx - 1); const WAYPOINT &wp = *decl.waypoint[idx]; // set name unicode2usascii(wp.Name, imiWp.name, sizeof(imiWp.name)); // set latitude TAngle a; double angle = wp.Latitude; if((a.sign = (angle < 0) ? 1 : 0) != 0) angle *= -1; a.degrees = static_cast<IMIDWORD>(angle); a.milliminutes = static_cast<IMIDWORD>((angle - a.degrees) * 60 * 1000); imiWp.lat = a.value; // set longitude angle = wp.Longitude; if((a.sign = (angle < 0) ? 1 : 0) != 0) angle *= -1; a.degrees = static_cast<IMIDWORD>(angle); a.milliminutes = static_cast<IMIDWORD>((angle - a.degrees) * 60 * 1000); imiWp.lon = a.value; // TAKEOFF and LANDING do not have OZs if(imiIdx == 0 || imiIdx == (unsigned)decl.num_waypoints + 1) return; // set observation zones if(imiIdx == 1) { // START imiWp.oz.style = 3; switch(StartLine) { case 0: // cylinder imiWp.oz.A1 = 1800; break; case 1: // line imiWp.oz.line_only = 1; break; case 2: // fai sector imiWp.oz.A1 = 450; break; } imiWp.oz.R1 = std::min((DWORD)250000, StartRadius); } else if(imiIdx == (unsigned)decl.num_waypoints) { // FINISH imiWp.oz.style = 4; switch(FinishLine) { case 0: // cylinder imiWp.oz.A1 = 1800; break; case 1: // line imiWp.oz.line_only = 1; break; case 2: // fai sector imiWp.oz.A1 = 450; break; } imiWp.oz.R1 = std::min((DWORD)250000, FinishRadius); } else { // TPs if(AATEnabled) { imiWp.oz.style = 1; switch(Task[idx].AATType) { case CIRCLE: imiWp.oz.A1 = 1800; imiWp.oz.R1 = std::min(250000, (int)Task[idx].AATCircleRadius); break; case SECTOR: imiWp.oz.A1 = ((int)(360 + Task[idx].AATFinishRadial - Task[idx].AATStartRadial) % 360) * 10 / 2; imiWp.oz.A12 = ((int)(Task[idx].AATStartRadial * 10) + 1800 + imiWp.oz.A1) % 3600; imiWp.oz.R1 = std::min(250000, (int)Task[idx].AATSectorRadius); break; } } else { imiWp.oz.style = 2; switch(SectorType) { case 0: // cylinder imiWp.oz.A1 = 1800; imiWp.oz.R1 = std::min((DWORD)250000, SectorRadius); break; case 1: // sector imiWp.oz.A1 = 450; imiWp.oz.R1 = std::min((DWORD)250000, SectorRadius); break; case 2: // German DAe 0.5/10 imiWp.oz.A1 = 450; imiWp.oz.R1 = 10000; imiWp.oz.A2 = 1800; imiWp.oz.R2 = 500; break; } } } // other unused data imiWp.oz.maxAlt = 0; imiWp.oz.reduce = 0; imiWp.oz.move = 0; }