/*
* 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