/*********************************************************************************************************************/ /*!@file txtFileHandler.cs * @brief Handle for Texas Instruments-txt files. * *====================================================================================================================\n * @copyright * * ___________________________________________________________________________________________________________________\n * Copyright (c) 2016 SENSUS, GmbH.\n * All Rights Reserved.\n * \n * Confidential property of\n * SENSUS GmbH,\n * Meineckestr. 10, 30880 LAATZEN, GERMANY\n * \n * Design by\n * Hard- und Softwareentwicklung Thomas Wiedebusch,\n * Ostermarsch 17c, 31191 ALGERMISSEN/UMMELN, GERMANY\n * \n *====================================================================================================================\n * @intro * *____________________________________________________________________________________________________________________\n * Functions:\n * Reading txt files,\n * Replacing bytes with CRC.\n * *====================================================================================================================\n * @version * *____________________________________________________________________________________________________________________\n * V1.00 25-Feb-2016..27-Feb-2016 by Thomas Wiedebusch\n * - Initial. * * *====================================================================================================================\n */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace CRC_CCITT { /*---------------------------------------------------------------------------------------------------------------*/ /*!@brief txtFileHandler class. * @author Thomas Wiedebusch * @date 25-Feb-2016 * */ /*---------------------------------------------------------------------------------------------------------------*/ class txtFileHandler_t { //class variables String inputFile_str; //file name String outputFile_str; //file name String fileLine_str; //one line of the file crcGenrator_memSetFn_t MemSetFn_vdp; //set data to address of working memory crcGenrator_memGetFn_t MemGetFn_u8p; //get data from working memory UInt32 crcFileLineBaseAddress_u32 = 0; //CRC file line address reminder set during input file processing UInt32 crcFileLine_u32 = 0; //CRC address line in file reminder set during input file processing bool crcFileLineFound_bol = false; //CRC address in file found reminder UInt32 memAddressCtr_u32 = 0; //CRC memory address counter bool placeCrcToFile_bol; //CRC output to file is required UInt32 crcAddress_u32; //CRC address given as parameter at startup //txt file markers const Char addressMarker_cchr = '@'; //base address marker const Char endOfFileMarker_cchr = 'q'; //end of file marker const Byte maxDataOfFileLine_cu8 = 16; //maximum data at one file line const Byte fileLineDataCellIncrement_cu8 = 3; //3 digits increment for one data byte e.g. A5_ //calculations UInt32 fileLineCtr_u32 = 0; //actual accessed file line bool memoryAddressSetup_bol = false; //initial memory address has been set /*---------------------------------------------------------------------------------------------------------------*/ /*!@brief Constructor for txt file handler class:\n * -initializes file,\n * -this constructor will only be called if the input file has been found,\n * -sets delegates to memory set and get function being able to dispatch read data.\n * @author Thomas Wiedebusch * @date 25-Feb-2016 * @param[in] inputFileIn_str file name for input file * @param[in] outputFileIn_str file name for output file, can be identical with input file * @param[in] MemSetInFn_vdp set function to dispatch data to memory * @param[in] MemGetInFn_vdp get function to read data from memory * */ /*---------------------------------------------------------------------------------------------------------------*/ public txtFileHandler_t(String inputFileIn_str, String outputFileIn_str, crcGenrator_memSetFn_t MemSetInFn_vdp, crcGenrator_memGetFn_t MemGetInFn_u8p, UInt32 crcAddressIn_u32, bool placeCrcToFileIn_bol) { inputFile_str = inputFileIn_str; outputFile_str = outputFileIn_str; MemSetFn_vdp = MemSetInFn_vdp; MemGetFn_u8p = MemGetInFn_u8p; placeCrcToFile_bol = placeCrcToFileIn_bol; crcAddress_u32 = crcAddressIn_u32; } /**/ /*---------------------------------------------------------------------------------------------------------------*/ /*!@brief Read file and dispatch the data to the CRC generator:\n * -reads every line and checks format. * @author Thomas Wiedebusch * @date 25-Feb-2016 * @return file format valid * */ /*---------------------------------------------------------------------------------------------------------------*/ public bool ValidateInputFile_bol() { bool returnValue_bol = false; fileLineCtr_u32 = 0; try { //check if file exits if (File.Exists(inputFile_str)) { //opens file for read StreamReader inputFile_st = new StreamReader(inputFile_str); //read single line until file end or validation failed do { fileLine_str = inputFile_st.ReadLine(); //decode the file line returnValue_bol = ProcessInputFileLine_bol(); //change file line counter after check and line counter reminder for the records fileLineCtr_u32++; } while (returnValue_bol && !inputFile_st.EndOfStream); //release file inputFile_st.Close(); } }//try catch { } return returnValue_bol; } /**/ /*---------------------------------------------------------------------------------------------------------------*/ /*!@brief Extract the information given by the read line from file:\n * -builds base address from '@' input,\n * -extracts bytes and dispatches these to CRC generator memory,\n * -searches for CRC address and reminds file line for this,\n * -validates file with file end marker 'q'. * @author Thomas Wiedebusch * @date 25-Feb-2016..26-Feb-2016 * @return txt file valid * */ /*---------------------------------------------------------------------------------------------------------------*/ bool ProcessInputFileLine_bol() { bool returnValue_bol = false; try { //read first byte of line Char lineStart_chr = fileLine_str[0]; switch (lineStart_chr) { case addressMarker_cchr: //extract new base address String mem_str = fileLine_str.Substring(1, fileLine_str.Length - 1); memAddressCtr_u32 = UInt32.Parse( mem_str, System.Globalization.NumberStyles.HexNumber); //check memory address range if( crcGenerator_t.maxMemBytes_cu32 > memAddressCtr_u32) { memoryAddressSetup_bol = true; returnValue_bol = true; } break; case endOfFileMarker_cchr: //if end of file marker read on first line then the file is invalid if (0 != fileLineCtr_u32) { returnValue_bol = true; } break; default: //if data read on first line then the file is invalid if ((0 != fileLineCtr_u32) && (memoryAddressSetup_bol)) { Byte data_u8; Byte fileLineDataCtr_u8 = 0; String data_str; //remind the base address of this file line to save it for CRC replacement UInt32 fileLineBaseAddress_u32 = memAddressCtr_u32; //search file line for (Byte ctr_u8 = 0; ctr_u8 < maxDataOfFileLine_cu8; ctr_u8++) { //inner loop limitation to actual file line length while (fileLine_str.Length > fileLineDataCtr_u8) { //remind file line for CRC output if (crcAddress_u32 == memAddressCtr_u32) { //remind the file entry crcFileLine_u32 = fileLineCtr_u32; //remind the base address for the file line for CRC replacement crcFileLineBaseAddress_u32 = fileLineBaseAddress_u32; //mark that entry has been found crcFileLineFound_bol = true; } //extract data data_str = fileLine_str.Substring(fileLineDataCtr_u8, fileLineDataCellIncrement_cu8); data_u8 = Byte.Parse(data_str, System.Globalization.NumberStyles.HexNumber); //dispatch data to CRC generator MemSetFn_vdp(memAddressCtr_u32, data_u8); memAddressCtr_u32++; fileLineDataCtr_u8 += fileLineDataCellIncrement_cu8; }//file line length }//data counter returnValue_bol = true; } break; }//switch }//try catch { } return returnValue_bol; } /**/ /*---------------------------------------------------------------------------------------------------------------*/ /*!@brief Read input file and store it to output file:\n * -reads every line, format has been checked,\n * -replaces CRC if required. * @author Thomas Wiedebusch * @date 25-Feb-2016..26-Feb-2016 * @param[in] crcResult_u16 result of CRC calculation * */ /*---------------------------------------------------------------------------------------------------------------*/ public void CreateOutputFile_vd(UInt16 crcResult_u16) { //the file line counter will be used to reference the input of already detected records fileLineCtr_u32 = 0; try { //check if file exits if (File.Exists(inputFile_str)) { //opens file for read StreamReader inputFile_st = new StreamReader(inputFile_str); if (File.Exists(outputFile_str)) { //erase it File.Delete(outputFile_str); } //open it for write access StreamWriter outputFile_st = new StreamWriter(outputFile_str, true); //read single line until and output it to the output file do { //read one line of the input file fileLine_str = inputFile_st.ReadLine(); //output of CRC to file is required if (placeCrcToFile_bol) { //if CRC address is not in file generate a new address with CRC only at the beginning if (!crcFileLineFound_bol) { //build a new file entry for CRC which is not inside the file address range BuildAndWriteNewCrc_vd(crcResult_u16, outputFile_st); //remove CRC to file request placeCrcToFile_bol = false; } //search for file entry to replace CRC else if (crcFileLine_u32 == fileLineCtr_u32) { //the base address for this file line has been set in advance during file scan ReplaceCrcData_vd(crcResult_u16); //remove CRC to file request placeCrcToFile_bol = false; } }//output of CRC to file is required //write all lines to output file outputFile_st.WriteLine(fileLine_str); //change file line of input file fileLineCtr_u32++; } while (!inputFile_st.EndOfStream); //release files inputFile_st.Close(); outputFile_st.Close(); //if the output file is equal to the input file, erase input file and rename temporary output file if (crcProgram_t.fileUndefined_cstr == outputFile_str) { File.Delete(inputFile_str); if (File.Exists(outputFile_str)) { //rename output to input file name, output file will be deleted File.Move(outputFile_str, inputFile_str); } } }//input file exists }//try catch { } } /**/ /*---------------------------------------------------------------------------------------------------------------*/ /*!@brief Replaces the CRC data if CRC address is inside the file address range:\n * -search for CRC address,\n * -replace CRC data in fileLine_str. * @author Thomas Wiedebusch * @date 26-Feb-2016..27-Feb-2016 * @param[in] crcResult_u16 result of CRC calculation * */ /*---------------------------------------------------------------------------------------------------------------*/ void ReplaceCrcData_vd(UInt16 crcResult_u16) { //build the CRC sub string for replacement Byte dataLsb_u8 = (Byte)(crcResult_u16 & 0x00FF); Byte dataMsb_u8 = (Byte)((crcResult_u16 >> 8) & 0x00FF); String crcSubStringOutput_str = dataLsb_u8.ToString("X2") + " " + dataMsb_u8.ToString("X2") + " "; //search for address entry in file memAddressCtr_u32 = crcFileLineBaseAddress_u32; UInt32 beforeCrcAddress_u32 = crcFileLineBaseAddress_u32; Byte ctr_u8 = 0; while (memAddressCtr_u32 < crcAddress_u32) { ctr_u8 += fileLineDataCellIncrement_cu8; memAddressCtr_u32++; } //extract string before CRC address from fileLine_str String beforeCrcAddress_str = ""; if (beforeCrcAddress_u32 < crcAddress_u32) { beforeCrcAddress_str = fileLine_str.Substring(0, ctr_u8); } //extract string after CRC address from fileLine_str String afterCrcAddress_str = ""; if (fileLine_str.Length > ctr_u8 + 2 * fileLineDataCellIncrement_cu8) { afterCrcAddress_str = fileLine_str.Substring(ctr_u8 + 2 * fileLineDataCellIncrement_cu8, fileLine_str.Length - (ctr_u8 + 2 * fileLineDataCellIncrement_cu8)); } //replace fileLine_str with substring at ctr position fileLine_str = beforeCrcAddress_str + crcSubStringOutput_str + afterCrcAddress_str; } /**/ /*---------------------------------------------------------------------------------------------------------------*/ /*!@brief Builds and writes a new CRC entry if CRC address is outside the file address range:\n * -assemble and write CRC address,\n * -assemble and write CRC data. * @author Thomas Wiedebusch * @date 26-Feb-2016 * @param[in] crcResult_u16 result of CRC calculation * @param[in] outputFile_st output file stream object * */ /*---------------------------------------------------------------------------------------------------------------*/ void BuildAndWriteNewCrc_vd(UInt16 crcResult_u16, StreamWriter outputFile_st) { //build the NEW address for CRC String crcOutput_str = addressMarker_cchr.ToString(); crcOutput_str += crcAddress_u32.ToString("X"); //write address to file outputFile_st.WriteLine(crcOutput_str); //build the CRC file line (line contains CRC only) Byte dataLsb_u8, dataMsb_u8; dataLsb_u8 = (Byte)(crcResult_u16 & 0x00FF); dataMsb_u8 = (Byte)((crcResult_u16 >> 8) & 0x00FF); crcOutput_str = dataLsb_u8.ToString("X2") + " " + dataMsb_u8.ToString("X2"); //write CRC data to file outputFile_st.WriteLine(crcOutput_str); } /**/ /*---------------------------------------------------------------------------------------------------------------*/ }//class txtFileHandler }//namespace CRC_CCITT /*=====================================END OF FILE===================================================================*/