/// <summary>
        /// Get the next record data
        /// </summary>
        /// <param name="rec">Record data</param>
        /// <returns>True if the operation was succesfull</returns>
        public bool getNextUpdaterData(ref s19rec rec)
        {
            bool bOk = false;

            do
            {
                m_currentIdx++;
                if (m_currentIdx >= m_aS19Data.Count)
                {
                    return(false);
                }

                if (checkDataType(getS19RecType(m_currentIdx)))
                {
                    rec = getS19Rec(m_currentIdx);
                    bOk = true;
                }
            } while (!bOk);

            return(true);
        }
        public string[] ConvertS19Data(int iLengthDataBlock)
        {
            List <string> sTarget           = new List <string>();
            int           icount            = recordCount();
            s19rec        rec               = default(s19rec);
            int           recDecimalAddress = 0;
            int           recDataLength     = 0;

            List <dataBlock> listDataBlock        = new List <dataBlock>();
            List <dataBlock> listAlignedDataBlock = new List <dataBlock>();
            List <byte>      currentBlockData     = new List <byte>();
            int currentBlockAddress = 0;
            //Dim prevBlockData As New List(Of Byte)
            //Dim prevBlockAddress As Integer = 0
            int         nextStartAddress = 0;
            List <byte> bytesTemp        = new List <byte>();

            for (var i = 0; i <= icount - 1; i++)
            {
                rec = getS19Rec(System.Convert.ToInt32(i));

                switch (rec.type)
                {
                case '0':
                    myAddS19Record(sTarget, rec.type, convBytesToHexa(rec.address.ToArray()), convBytesToHexa(rec.data.ToArray()));
                    break;

                case '1':
                    break;

                case '2':
                    break;

                case '3':

                    //dirección y longitud del bloque de datos
                    recDecimalAddress = RoutinesLibrary.Data.DataType.IntegerUtils.BytesToInt(rec.address.ToArray(), true);     //is BigEndian
                    recDataLength     = rec.data.Count;

                    //address gap
                    if (recDecimalAddress > nextStartAddress)
                    {
                        //new block. recording cumulative data
                        if (currentBlockData.Count > 0)
                        {
                            dataBlock block = new dataBlock(currentBlockAddress, currentBlockData.ToArray());
                            listDataBlock.Add(block);
                        }

                        //accumulates new data
                        currentBlockData.Clear();
                        currentBlockData.AddRange(rec.data.ToArray());
                        currentBlockAddress = recDecimalAddress;

                        //no gap
                    }
                    else
                    {
                        //add to current block
                        currentBlockData.AddRange(rec.data.ToArray());
                    }

                    //calculate next address, to control gaps
                    nextStartAddress = recDecimalAddress + recDataLength;
                    break;

                case '5':
                    break;

                case '7':
                case '8':
                case '9':
                    break;
                }
            }

            //add remaining data in last block
            if (currentBlockData.Count > 0)
            {
                dataBlock block = new dataBlock(currentBlockAddress, currentBlockData.ToArray());
                listDataBlock.Add(block);
            }


            //'Align all directions to 128 (iLengthDataBlock)
            //For i = 0 To listDataBlock.Count - 1
            //    If listDataBlock.Item(i).m_Address Mod iLengthDataBlock <> 0 Then

            //        'Calculamos el gap inicial
            //        Dim nInitialGap As Integer = listDataBlock.Item(i).m_Address - ((listDataBlock.Item(i).m_Address \ 128) * 128)

            //        'Rellenamos los datos iniciales con FF
            //        Dim alignData(listDataBlock.Item(i).m_Data.Length + nInitialGap - 1) As Byte
            //        setArrayTo(alignData, &HFF)
            //        Array.Copy(listDataBlock.Item(i).m_Data, 0, alignData, nInitialGap, listDataBlock.Item(i).m_Data.Length)

            //        'Actualizamos el array de datos
            //        listDataBlock.Item(i).m_Data = alignData

            //        'Actualizamos el address
            //        listDataBlock.Item(i).m_Address -= nInitialGap
            //    End If
            //Next

            //Align all directions to 128

            int lastAlignedDataBlock = -1;

            for (var i = 0; i <= listDataBlock.Count - 1; i++)
            {
                lastAlignedDataBlock = listAlignedDataBlock.Count - 1;

                if (listDataBlock[System.Convert.ToInt32(i)].m_Address % iLengthDataBlock != 0)
                {
                    //If listDataBlock.Item(i).m_Address > 486635784 Then
                    //    MsgBox("> 486635784")
                    //End If

                    int    nInitialGap               = 0;
                    int    nEndGap                   = 0;
                    byte[] alignData                 = null;
                    int    nCopyDataLength           = 0;
                    int    nTargetBufferToCopyLength = 0;

                    // ver si la dirección está dentro del bloque alineado anterior (múltiplo de 128)
                    bool bAlignBlock = true;
                    if (i > 0 & lastAlignedDataBlock >= 0)
                    {
                        int iPreviousBlockAddress       = System.Convert.ToInt32(listAlignedDataBlock[lastAlignedDataBlock].m_Address);
                        int iPreviousBlockDataLength    = System.Convert.ToInt32(listAlignedDataBlock[lastAlignedDataBlock].m_Data.Length);
                        int iPreviousBlockAlignedBlocks = iPreviousBlockDataLength / iLengthDataBlock;
                        if (iPreviousBlockDataLength / iLengthDataBlock != (double)iPreviousBlockDataLength / iLengthDataBlock)
                        {
                            iPreviousBlockAlignedBlocks++;
                        }
                        if (listDataBlock[System.Convert.ToInt32(i)].m_Address < iPreviousBlockAddress + (iPreviousBlockAlignedBlocks * iLengthDataBlock))
                        {
                            // copiar parte de los datos al bloque anterior
                            // primero el gap entre el fin de datos y la nueva dirección
                            nEndGap = System.Convert.ToInt32(listDataBlock[System.Convert.ToInt32(i)].m_Address - (iPreviousBlockAddress + iPreviousBlockDataLength));
                            // espacio que tengo para copiar = el total alineado menos los datos existentes y el gap añadido
                            nTargetBufferToCopyLength = (iPreviousBlockAlignedBlocks * iLengthDataBlock) - (iPreviousBlockDataLength + nEndGap);
                            // datos a copiar: mínimo entre espacio destino y datos origen
                            nCopyDataLength = Math.Min(nTargetBufferToCopyLength, System.Convert.ToInt32(listDataBlock[System.Convert.ToInt32(i)].m_Data.Length));
                            //Rellenamos los datos iniciales con FF
                            alignData = new byte[nEndGap + nCopyDataLength - 1 + 1];
                            setArrayTo(ref alignData, (byte)(0xFF));
                            Array.Copy((System.Array)(listDataBlock[System.Convert.ToInt32(i)].m_Data), 0, alignData, nEndGap, nCopyDataLength);
                            // copiar a bloque anterior
                            bytesTemp.Clear();
                            bytesTemp.AddRange(listAlignedDataBlock[lastAlignedDataBlock].m_Data);
                            bytesTemp.AddRange(alignData);
                            listAlignedDataBlock[lastAlignedDataBlock].m_Data = bytesTemp.ToArray();
                            // quitar estos datos del bloque actual y modificar address
                            bytesTemp.Clear();
                            bytesTemp.AddRange(listDataBlock[System.Convert.ToInt32(i)].m_Data);
                            bytesTemp.RemoveRange(0, nCopyDataLength);
                            if (bytesTemp.Count > 0)
                            {
                                listDataBlock[System.Convert.ToInt32(i)].m_Data = bytesTemp.ToArray();
                                // modificar address
                                listDataBlock[System.Convert.ToInt32(i)].m_Address = listDataBlock[System.Convert.ToInt32(i)].m_Address + nCopyDataLength;
                            }
                            else
                            {
                                bAlignBlock = false;
                            }
                        }
                    }

                    if (bAlignBlock)
                    {
                        //Calculamos el gap inicial
                        nInitialGap = System.Convert.ToInt32(listDataBlock[System.Convert.ToInt32(i)].m_Address - ((listDataBlock[System.Convert.ToInt32(i)].m_Address / iLengthDataBlock) * iLengthDataBlock));

                        //Rellenamos los datos iniciales con FF
                        alignData = new byte[listDataBlock[System.Convert.ToInt32(i)].m_Data.Length + nInitialGap - 1 + 1];
                        setArrayTo(ref alignData, (byte)(0xFF));
                        Array.Copy((System.Array)(listDataBlock[System.Convert.ToInt32(i)].m_Data), 0, alignData, nInitialGap, System.Convert.ToInt32(listDataBlock[System.Convert.ToInt32(i)].m_Data.Length));

                        //Actualizamos el array de datos
                        listDataBlock[System.Convert.ToInt32(i)].m_Data = alignData;

                        //Actualizamos el address
                        listDataBlock[System.Convert.ToInt32(i)].m_Address -= nInitialGap;

                        // add aligned block
                        listAlignedDataBlock.Add(listDataBlock[System.Convert.ToInt32(i)]);
                    }
                }
                else
                {
                    // add block, already aligned
                    listAlignedDataBlock.Add(listDataBlock[System.Convert.ToInt32(i)]);
                }
            }

            // build SREC in iDataBlock format
            byte[] newData = null;
            newData = new byte[iLengthDataBlock - 1 + 1];

            int iCopyLength          = 0;
            int iDataLengthRemainder = 0;
            int iAddress             = 0;

            int  nextStartByte = 0;
            int  iBlockNumber  = 0;
            bool bEnd          = false;


            //recorrer todos los bloques de datos
            //For i = 0 To listDataBlock.Count - 1
            for (var i = 0; i <= listAlignedDataBlock.Count - 1; i++)
            {
                //dirección y datos del bloque de datos
                //currentBlockAddress = listDataBlock.Item(i).m_Address
                currentBlockAddress = System.Convert.ToInt32(listAlignedDataBlock[System.Convert.ToInt32(i)].m_Address);
                currentBlockData.Clear();
                //currentBlockData.AddRange(listDataBlock.Item(i).m_Data)
                currentBlockData.AddRange(listAlignedDataBlock[System.Convert.ToInt32(i)].m_Data);

                //If currentBlockAddress > 486635784 Then
                //    MsgBox("> 486635784")
                //End If

                nextStartByte = 0;
                iBlockNumber  = 0;
                bEnd          = false;

                //loop por el bloque para dividir en direcciones de 128
                do
                {
                    //determinar cuanto queda por copiar
                    iDataLengthRemainder = currentBlockData.Count - nextStartByte;

                    if (iDataLengthRemainder > 0)
                    {
                        //copiamos un bloque entero de datos o el resto
                        if (iDataLengthRemainder > iLengthDataBlock)
                        {
                            iCopyLength = iLengthDataBlock;
                        }
                        else
                        {
                            iCopyLength = iDataLengthRemainder;
                        }

                        //número de bloque a copiar
                        iBlockNumber++;

                        //el buffer de 128 a HFF
                        setArrayTo(ref newData, (byte)(0xFF));

                        //copy data
                        Array.Copy(currentBlockData.ToArray(), nextStartByte, newData, 0, iCopyLength);

                        //la nueva dirección es la dirección base del bloque más la cantidad de bloques copiados
                        iAddress = currentBlockAddress + (iLengthDataBlock * (iBlockNumber - 1));

                        //grabar el bloque
                        myAddS19Record(sTarget, '3', convBytesToHexa(intToBytesAddress(iAddress, true)), convBytesToHexa(newData));

                        //actualizar la siguiente dirección
                        nextStartByte += iCopyLength;
                    }
                    else
                    {
                        bEnd = true;
                    }
                } while (!bEnd);
            }

            return(sTarget.ToArray());
        }
        /// <summary>
        /// Get record at a specific line
        /// </summary>
        /// <param name="idx">Record line index</param>
        /// <returns>Record</returns>
        private s19rec getS19Rec(int idx)
        {
            s19rec rec           = new s19rec();
            int    lengthHex     = 0;
            int    addressBytes  = 0;
            int    posDataHex    = 0;
            int    dataLengthHex = 0;

            // rec type (0 to 9)
            rec.type = getS19RecType(idx);

            // qty of bytes of address + data + checksum fields
            rec.length = int.Parse(System.Convert.ToString(m_aS19Data[idx].Substring(2, 2)), System.Globalization.NumberStyles.AllowHexSpecifier);
            lengthHex  = rec.length * 2;

            switch (rec.type)
            {
            case '0':
                addressBytes = 2;
                break;

            case '1':
                addressBytes = 2;     // data address 16 bit
                break;

            case '2':
                addressBytes = 3;     // data address 24 bit
                break;

            case '3':
                addressBytes = 4;     // data address 32 bit
                break;

            case '5':
                addressBytes = 2;     // S1+S2+S3 record count
                break;

            case '7':
                addressBytes = 4;     // starting address of the program 32 bit
                break;

            case '8':
                addressBytes = 3;     // starting address of the program 24 bit
                break;

            case '9':
                addressBytes = 2;     // starting address of the program 16 bit
                break;
            }

            //Address
            rec.address = convHexToByteArray(System.Convert.ToString(m_aS19Data[idx].Substring(4, addressBytes * 2)));

            //Posición inicial de data
            posDataHex = 2 + 2 + (addressBytes * 2); // Sx + length(2) + address hex length

            //Longitud de data
            dataLengthHex = lengthHex - (addressBytes * 2) - 2; // total hex length - address hex length - checksum(2)

            //Data
            if (dataLengthHex > 0)
            {
                rec.data = convHexToByteArray(System.Convert.ToString(m_aS19Data[idx].Substring(posDataHex, dataLengthHex)));
            }
            else
            {
                rec.data = new List <byte>();
            }

            //Checksum
            rec.checksum = convHexToByteArray(System.Convert.ToString(m_aS19Data[idx].Substring(posDataHex + dataLengthHex, 2)));

            return(rec);
        }