/* * fileIO.c - file read and write * Copyright (C) 2010-2021 Alberto Maccioni * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA * or see */ //configure for GUI or command-line #include "common.h" #include "progP12.h" #include "progP16.h" #include "progP18.h" #include "progP24.h" #include "progAVR.h" unsigned int htoi(const char *hex, int length) { int i; unsigned int v = 0; for (i = 0; i < length; i++) { v <<= 4; if (hex[i] >= '0' && hex[i] <= '9') v += hex[i] - '0'; else if (hex[i] >= 'a' && hex[i] <= 'f') v += hex[i] - 'a' + 10; else if (hex[i] >= 'A' && hex[i] <= 'F') v += hex[i] - 'A' + 10; else PrintMessage1(strings[S_Inohex],hex); //"Error: '%.4s' doesn't look very hexadecimal, right?\n" } return v; } void Save(char* dev,char* savefile) { FILE* f=fopen(savefile,"w"); if(!f) return; char str[512],str1[512]=""; int i,sum=0,count=0,ext=0,s,base; //**************** 10-16F ******************************************* if(!strncmp(dev,"10",2)||!strncmp(dev,"12",2)||!strncmp(dev,"16",2)){ int x=0x3fff,addr; //if(!strncmp(dev,"16",2)||!strncmp(dev,"12F6",4)) x=0x3fff; fprintf(f,":020000040000FA\n"); //extended address=0 for(i=0;i=x;i++); //remove leading 0xFFF for(;i>8)+(memCODE_W[i]&0xff); sprintf(str,"%02X%02X",memCODE_W[i]&0xff,memCODE_W[i]>>8); strcat(str1,str); count++; if(count==8||i==sizeW-1){ base=i-count+1; for(s=i;s>=base&&memCODE_W[s]>=x;s--){ //remove trailing 0xFFF sum-=(memCODE_W[s]>>8)+(memCODE_W[s]&0xff); str1[strlen(str1)-4]=0; } count-=i-s; addr=(s-count+1)*2; sum+=count*2+(addr&0xff)+(addr>>8); if(base>>15>ext){ ext=base>>15; fprintf(f,":02000004%04X%02X\n",ext,(-6-ext)&0xff); } if(count) fprintf(f,":%02X%04X00%s%02X\n",count*2,addr&0xFFFF,str1,(-sum)&0xff); str1[0]=0; count=sum=0; } } if(sizeEE){ //this is only for 16F1xxx if(ext!=0x01) fprintf(f,":020000040001F9\n"); for(i=0,count=sum=0;ii-count&&memEE[s]>=0xff;s--){ //remove trailing 0xFF sum-=memEE[s]&0xff; str1[strlen(str1)-4]=0; } count-=i-s; addr=(s-count+1)*2+0xE000; sum+=count*2+(addr&0xff)+(addr>>8); if(count){ fprintf(f,":%02X%04X00%s%02X\n",count*2,addr,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } } fprintf(f,":00000001FF\n"); } //**************** 18F ******************************************* else if(!strncmp(dev,"18F",3)){ fprintf(f,":020000040000FA\n"); //extended address=0 for(i=0;i=base&&memCODE[s]==0xff;s--){ //remove trailing 0xFF sum-=memCODE[s]; str1[strlen(str1)-2]=0; } count-=i-s; sum+=count+(base&0xff)+((base>>8)&0xff); if(base>>16>ext){ ext=base>>16; fprintf(f,":02000004%04X%02X\n",ext,(-6-ext)&0xff); } if(count){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } for(i=0,count=sum=0;i<8;i++){ sum+=memID[i]; sprintf(str,"%02X",memID[i]&0xff); strcat(str1,str); count++; if(count==8){ fprintf(f,":020000040020DA\n"); base=i-count+1; for(s=i;s>i-count&&memID[s]>=0xff;s--){ //remove trailing 0xFF sum-=memID[s]&0xff; str1[strlen(str1)-2]=0; } count-=i-s; sum+=count+(base&0xff)+((base>>8)&0xff); if(count){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } for(i=0,count=sum=0;i<14;i++){ sum+=memCONFIG[i]; sprintf(str,"%02X",memCONFIG[i]&0xff); strcat(str1,str); count++; if(count==14){ fprintf(f,":020000040030CA\n"); base=i-count+1; for(s=i;s>i-count&&memCONFIG[s]>=0xff;s--){ //remove trailing 0xFF sum-=memCONFIG[s]&0xff; str1[strlen(str1)-2]=0; } count-=i-s; sum+=count+(base&0xff)+((base>>8)&0xff); if(count){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } if(sizeEE){ fprintf(f,":0200000400F00A\n"); for(i=0,count=sum=0;ii-count&&memEE[s]>=0xff;s--){ //remove trailing 0xFF sum-=memEE[s]&0xff; str1[strlen(str1)-2]=0; } count-=i-s; sum+=count+(base&0xff)+((base>>8)&0xff); if(count){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } } fprintf(f,":00000001FF\n"); } //**************** 24F ******************************************* else if((!strncmp(dev,"24F",3)||!strncmp(dev,"24H",3)||!strncmp(dev,"24E",3)||!strncmp(dev,"30F",3)||!strncmp(dev,"33F",3)||!strncmp(dev,"33E",3))){ int valid; fprintf(f,":020000040000FA\n"); //extended address=0 int sum=0,count=0,s,word; word=memCODE[0]+(memCODE[1]<<8)+(memCODE[2]<<16)+(memCODE[3]<<24); for(i=0;i>8)&0xff); if(base>>16>ext){ ext=base>>16; fprintf(f,":02000004%04X%02X\n",ext,(-6-ext)&0xff); } if(count&&valid){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } if(sizeCONFIG){ fprintf(f,":0200000401F009\n"); for(i=0,count=sum=0;i>8)&0xff); if(count){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } } if(sizeEE){ fprintf(f,":0200000400FFFB\n"); str1[0]=0; for(i=0,count=sum=0;i>8); if(count&&valid){ fprintf(f,":%02X%04X00%s%02X\n",count,base+0xE000,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } } fprintf(f,":00000001FF\n"); } //**************** ATxxxx ******************************************* else if(!strncmp(dev,"AT",2)){ fprintf(f,":020000040000FA\n"); //extended address=0 for(i=0;i=base&&memCODE[s]==0xff;s--){ //remove trailing 0xFF sum-=memCODE[s]; str1[strlen(str1)-2]=0; } count-=i-s; sum+=count+(base&0xff)+((base>>8)&0xff); if(base>>16>ext){ ext=base>>16; fprintf(f,":02000004%04X%02X\n",ext,(-6-ext)&0xff); } if(count){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } fprintf(f,":00000001FF\n"); } //**************** 24xxx / 93xxx / 25xxx / 95xxx / DSxxxx ******************************************* else if(!strncmp(dev,"24",2)||!strncmp(dev,"93",2)||!strncmp(dev,"25",2)||!strncmp(dev,"95",2)||\ !strncmp(dev,"DS",2)||!strncmp(dev,"11",2)){ if(strstr(savefile,".bin")||strstr(savefile,".BIN")){ #ifdef _WIN32 //brain-damaged op. systems need this to avoid messing with some bytes f=freopen(savefile,"wb",f); if(!f) return; #endif fwrite(memEE,1,sizeEE,f); } else{ //HEX int valid; fprintf(f,":020000040000FA\n"); //extended address=0 for(i=0;i>8)&0xff); if(base>>16>ext){ ext=base>>16; fprintf(f,":02000004%04X%02X\n",ext,(-6-ext)&0xff); } if(count){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } } str1[0]=0; count=sum=0; } } fprintf(f,":00000001FF\n"); } } if(f) fclose(f); } void SaveEE(char* dev,char* savefile){ FILE* f=fopen(savefile,"w"); if(!f) return; //**************** ATMEL ******************************************* if(!strncmp(dev,"AT",2)){ char str[512],str1[512]=""; int i,base; fprintf(f,":020000040000FA\n"); //extended address=0 int sum=0,count=0,s; for(i=0,count=sum=0;ii-count&&memEE[s]>=0xff;s--){ //remove trailing 0xFF sum-=memEE[s]&0xff; str1[strlen(str1)-2]=0; } count-=i-s; sum+=count+(base&0xff)+((base>>8)&0xff); if(count){ fprintf(f,":%02X%04X00%s%02X\n",count,base&0xFFFF,str1,(-sum)&0xff); } str1[0]=0; count=sum=0; } } fprintf(f,":00000001FF\n"); } if(f) fclose(f); } int Load(char*dev,char*loadfile){ int i,input_address=0,ext_addr=0,sum,valid; char line[256]; FILE* f=fopen(loadfile,"r"); if(!f) return -1; PrintMessage1("%s :\r\n",loadfile); //**************** 10-16F ******************************************* if(!strncmp(dev,"10",2)||!strncmp(dev,"12",2)||!strncmp(dev,"16",2)){ unsigned char buffer[0x20000],bufferEE[0x1000]; int sizeM=0; memset(buffer,0xFF,sizeof(buffer)); memset(bufferEE,0xFF,sizeof(bufferEE)); sizeEE=0; for(;fgets(line,256,f);){ if(strlen(line)>9&&line[0]==':'){ int hex_count = htoi(line+1, 2); if((int)strlen(line)-11sizeW) sizeW=sizeM; for (i=0;i=0x1E000&&input_address<0x1F000){ //EEPROM sizeM=(input_address-0x1E000+hex_count)/2; if(sizeM>sizeEE) sizeEE=sizeM; for (i=0;i14) ext_addr=htoi(line+9,4); break; default: break; } } } } } sizeW/=2; if(memCODE_W) free(memCODE_W); memCODE_W=(WORD*)malloc(sizeof(WORD)*sizeW); for(i=0;i0x8000?0x8500:0x2100; DisplayCODE16F(imax); if(sizeW>=0x2100&&sizeW<0x3000){ //EEPROM@0x2100 PrintMessage(strings[S_EEMem]); //"\r\nEEPROM memory:\r\n" DisplayEE16F(0x700); } else if(sizeEE) DisplayEE(); PrintMessage("\r\n"); } //**************** 18F ******************************************* else if(!strncmp(dev,"18F",3)){ unsigned char buffer[0x30000],bufferEE[0x1000]; int sizeM; memset(buffer,0xFF,sizeof(buffer)); memset(bufferEE,0xFF,sizeof(bufferEE)); memset(memID,0xFF,sizeof(memID)); memset(memCONFIG,0xFF,sizeof(memCONFIG)); for(;fgets(line,256,f);){ if(strlen(line)>9&&line[0]==':'){ int hex_count = htoi(line+1, 2); if((int)strlen(line) - 11 < hex_count * 2) { PrintMessage1(strings[S_IhexShort],line); //"Intel hex8 line too short:\r\n%s\r\n" } else{ input_address=htoi(line+3,4); sum=0; for (i=1;i<=hex_count*2+9;i+=2) sum += htoi(line+i,2); if ((sum & 0xff)!=0) { PrintMessage1(strings[S_IhexChecksum],line); //"Intel hex8 checksum error in line:\r\n%s\r\n" } else{ switch(htoi(line+7,2)){ case 0: //Data record if(ext_addr<0x20){ //Code <0x200000 sizeM=(ext_addr<<16)+input_address+hex_count; if(sizeM>size) size=sizeM; for (i=0;isizeEE) sizeEE=sizeM; } break; case 4: //extended linear address record if(strlen(line)>14) ext_addr=htoi(line+9,4); break; default: break; } } } } } if(memCODE) free(memCODE); memCODE=(unsigned char*)malloc(size); memcpy(memCODE,buffer,size); if(memEE) free(memEE); memEE=(unsigned char*)malloc(sizeEE); memcpy(memEE,bufferEE,sizeEE); PrintMessage(strings[S_IDMem]); //"ID memory:\r\n" for(i=0;i<8;i+=2) PrintMessage4("ID%d: 0x%02X ID%d: 0x%02X\r\n",i,memID[i],i+1,memID[i+1]); PrintMessage(strings[S_ConfigMem]); //"CONFIG memory:\r\n" for(i=0;i<7;i++){ PrintMessage2(strings[S_ConfigWordH],i+1,memCONFIG[i*2+1]); //"CONFIG%dH: 0x%02X\t" PrintMessage2(strings[S_ConfigWordL],i+1,memCONFIG[i*2]); //"CONFIG%dL: 0x%02X\r\n" } PrintMessage(strings[S_CodeMem]); //"\r\nCODE memory:\r\n" DisplayCODE18F(size); if(sizeEE) DisplayEE(); PrintMessage("\r\n"); } //**************** 24F ******************************************* else if(!strncmp(dev,"24F",3)||!strncmp(dev,"24H",3)||!strncmp(dev,"24E",3)||!strncmp(dev,"30F",3)||!strncmp(dev,"33F",3)||!strncmp(dev,"33E",3)){ unsigned char *buffer,bufferEE[0x2000]; int d; buffer=(unsigned char*)malloc(0x100000); memset(buffer,0xFF,0x100000); memset(bufferEE,0xFF,sizeof(bufferEE)); memset(memCONFIG,0xFF,sizeof(memCONFIG)); memset(memUSERID,0xFF,sizeof(memUSERID)); sizeUSERID=0; for(;fgets(line,256,f);){ if(strlen(line)>9&&line[0]==':'){ int hex_count = htoi(line+1, 2); if((int)strlen(line) - 11 < hex_count * 2) { PrintMessage1(strings[S_IhexShort],line); //"Intel hex8 line too short:\r\n%s\r\n" } else{ input_address=htoi(line+3,4); sum=0; for (i=1;i<=hex_count*2+9;i+=2) sum += htoi(line+i,2); if ((sum & 0xff)!=0) { PrintMessage1(strings[S_IhexChecksum],line); //"Intel hex8 checksum error in line:\r\n%s\r\n" } else{ switch(htoi(line+7,2)){ case 0: //Data record if(ext_addr<0x20){ //Code int end1=(ext_addr<<16)+input_address+hex_count; if(size=0xE000){ //EEPROM for (i=0;i14) ext_addr=htoi(line+9,4); break; default: break; } } } } } if(memCODE) free(memCODE); memCODE=(unsigned char*)malloc(size); memcpy(memCODE,buffer,size); free(buffer); sizeEE=sizeEE?0x1000:0; if(memEE) free(memEE); memEE=(unsigned char*)malloc(sizeEE); for(i=0;i9&&line[0]==':'){ int hex_count = htoi(line+1, 2); if((int)strlen(line) - 11 < hex_count * 2) { PrintMessage1(strings[S_IhexShort],line); //"Intel hex8 line too short:\r\n%s\r\n" } else{ input_address=htoi(line+3,4); sum=0; for (i=1;i<=hex_count*2+9;i+=2) sum += htoi(line+i,2); if ((sum & 0xff)!=0) { PrintMessage1(strings[S_IhexChecksum],line); //"Intel hex8 checksum error in line:\r\n%s\r\n" } else{ switch(htoi(line+7,2)){ case 0: //Data record if(ext_addr<0x20){ //Code size=input_address+hex_count; for (i=0;i14) ext_addr=htoi(line+9,4); break; default: break; } } } } } if(memCODE) free(memCODE); memCODE=(unsigned char*)malloc(size); memcpy(memCODE,buffer,size); if(size) PrintMessage(strings[S_CodeMem]); //"\r\nmemoria CODICE:\r\n" DisplayCODEAVR(size); PrintMessage("\r\n"); } //**************** 24xxx / 93xxx / 25xxx / 95xxx / DSxxxx /11xxx ******************************* else if(!strncmp(dev,"24",2)||!strncmp(dev,"93",2)||!strncmp(dev,"25",2)||!strncmp(dev,"95",2)||\ !strncmp(dev,"DS",2)||!strncmp(dev,"11",2)){ if(strstr(loadfile,".bin")||strstr(loadfile,".BIN")){ #ifdef _WIN32 //brain-damaged op. systems need this to avoid messing with some bytes f=freopen(loadfile,"rb",f); if(!f) return -1; #endif fseek(f, 0L, SEEK_END); sizeEE=ftell(f); fseek(f, 0L, SEEK_SET); if(sizeEE>0x1000000) sizeEE=0x1000000; //max 16MB if(memEE) free(memEE); memEE=(unsigned char*)malloc(sizeEE); sizeEE=fread(memEE,1,sizeEE,f); } else{ //Hex file int bufSize=0x40000; //256K unsigned char *bufferEE=(unsigned char*)malloc(bufSize); memset(bufferEE,0xFF,bufSize); for(;fgets(line,256,f);){ if(strlen(line)>9&&line[0]==':'){ int hex_count = htoi(line+1, 2); if((int)strlen(line) - 11 < hex_count * 2) { PrintMessage1(strings[S_IhexShort],line); //"Intel hex8 line too short:\r\n%s\r\n" } else{ input_address=htoi(line+3,4); sum=0; int end1; for (i=1;i<=hex_count*2+9;i+=2) sum+=htoi(line+i,2); if ((sum & 0xff)!=0) { PrintMessage1(strings[S_IhexChecksum],line); //"Intel hex8 checksum error in line:\r\n%s\r\n" } else{ switch(htoi(line+7,2)){ case 0: //Data record end1=(ext_addr<<16)+input_address+hex_count; if(end1>=0x1000000) break; //max 16MB if(sizeEE14) ext_addr=htoi(line+9,4); break; default: break; } } } } } if(memEE) free(memEE); memEE=(unsigned char*)malloc(sizeEE); memcpy(memEE,bufferEE,sizeEE); free(bufferEE); } DisplayEE(); //visualize int sum=0; for(i=0;i9&&line[0]==':'){ int hex_count = htoi(line+1, 2); if((int)strlen(line) - 11 < hex_count * 2) { PrintMessage1(strings[S_IhexShort],line); //"Intel hex8 line too short:\r\n%s\r\n" } else{ input_address=htoi(line+3,4); int sum = 0; for (i=1;i<=hex_count*2+9;i+=2) sum+=htoi(line+i,2); if ((sum & 0xff)!=0) { PrintMessage1(strings[S_IhexChecksum],line); //"Intel hex8 checksum error in line:\r\n%s\r\n" } else{ switch(htoi(line+7,2)){ case 0: //Data record if(ext_addr==0&&input_address<0x1000){ //EEPROM for (i=0;i14) ext_addr=htoi(line+9,4); break; default: break; } } } } } if(memEE) free(memEE); memEE=(unsigned char*)malloc(sizeEE); memcpy(memEE,bufferEE,sizeEE); if(sizeEE) DisplayEE(); //visualize PrintMessage("\r\n"); fclose(f); } } void OpenLogFile() { logfile=fopen(LogFileName,"w"); if(!logfile) return; fprintf(logfile,_APPNAME " version %s (%s)\n",VERSION,SYSNAME); fprintf(logfile,"Firmware version %d.%d.%d\n",FWVersion>>16,(FWVersion>>8)&0xFF,FWVersion&0xFF); struct tm * timeinfo; time_t rawtime; time( &rawtime ); /* Get time as long integer. */ timeinfo = localtime( &rawtime ); /* Convert to local time. */ fprintf(logfile,"%s\n", asctime (timeinfo) ); } void CloseLogFile() { if(logfile)fclose(logfile); logfile=0; } void WriteLogIO() { int i; //fprintf(logfile,"bufferU=[%02X\n",bufferU[0]); fprintf(logfile,"bufferU=["); for(i=0;i