/* * op.c - control program for the open programmer * Copyright (C) 2009-2020 Alberto Maccioni * for detailed info see: * http://openprog.altervista.org/ * * 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 */ #include "common.h" #include "common_functions.h" #include "I2CSPI.h" #include "deviceRW.h" #include "fileIO.h" #include "progAVR.h" #if !defined _WIN32 && !defined __CYGWIN__ #include int kbhit() { struct timeval tv; fd_set read_fd; tv.tv_sec=0; tv.tv_usec=0; FD_ZERO(&read_fd); FD_SET(0,&read_fd); if(select(1, &read_fd, NULL, NULL, &tv) == -1) return 0; if(FD_ISSET(0,&read_fd)) return 1; return 0; } #define getch getchar #else #include "conio.h" #endif int info=0; int devType=0x10000; char dev[64]=""; void msDelay(double delay); void TestHw(); int StartHVReg(double V); void DisplayEE(); int FindDevice(); int main (int argc, char **argv) { int ee=0,r=0,ver=0,c=0,support=0,i2c=0,spi_mode=0,i,j,testhw=0,s1=0; int spi_speed=0,command=0,langfile=0,help=0; char lang[32]=""; unsigned char tmpbuf[128]; opterr = 0; int option_index = 0; int fuse3k=0; char* langid=0; int cw1,cw2,cw3,cw4,cw5,cw6,cw7; cw1=cw2=cw3=cw4=cw5=cw6=cw7=0x10000; #if defined _WIN32 || defined __CYGWIN__ //Windows bufferI=bufferI0+1; bufferU=bufferU0+1; bufferI0[0]=0; bufferU0[0]=0; #endif struct option long_options[] = { {"BKosccal", no_argument, &load_BKosccal, 1}, {"calib", no_argument, &load_calibword, 1}, {"command", no_argument, &command, 1}, {"cw1", required_argument, 0, '1'}, {"cw2", required_argument, 0, '2'}, {"cw3", required_argument, 0, '3'}, {"cw4", required_argument, 0, '4'}, {"cw5", required_argument, 0, '5'}, {"cw6", required_argument, 0, '6'}, {"cw7", required_argument, 0, '7'}, {"d", required_argument, 0, 'd'}, {"device", required_argument, 0, 'd'}, {"ee", no_argument, &ee, 1}, {"err", required_argument, 0, 'e'}, {"fuse", required_argument, 0, 'f'}, {"fuseh", required_argument, 0, 'F'}, {"fusex", required_argument, 0, 'X'}, {"fuse3k", required_argument, 0, 'k'}, {"h", no_argument, &help,1}, {"help", no_argument, &help,1}, {"HWtest", no_argument, &testhw, 1}, {"info", no_argument, &info, 1}, {"i", no_argument, &info, 1}, {"i2c_r", no_argument, &i2c, 1}, {"i2c_r2", no_argument, &i2c, 2}, {"i2c_w", no_argument, &i2c, 3}, {"i2c_w2", no_argument, &i2c, 4}, {"i2cspeed", required_argument, 0, 'D'}, {"id", no_argument, &programID, 1}, {"icd", required_argument, 0, 'I'}, {"l", optional_argument, 0, 'l'}, //-l=val {"log", optional_argument, 0, 'l'}, {"lang", required_argument, 0, 'n'}, {"langfile", no_argument, &langfile, 1}, {"lock", required_argument, 0, 'L'}, {"mode", required_argument, 0, 'm'}, {"nolvcheck", no_argument, &skipV33check, 1}, {"osccal", no_argument, &load_osccal, 1}, #if !defined _WIN32 && !defined __CYGWIN__ {"p", required_argument, 0, 'p'}, {"path", required_argument, 0, 'p'}, #endif {"pid", required_argument, 0, 'P'}, {"rep" , required_argument, 0, 'R'}, {"reserved", no_argument, &r, 1}, {"r", no_argument, &r, 1}, {"s1", no_argument, &s1, 1}, {"S1", no_argument, &s1, 1}, {"s", required_argument, 0, 's'}, {"save", required_argument, 0, 's'}, {"saveEE", required_argument, 0, 'S'}, {"se", required_argument, 0, 'S'}, {"spi_r", no_argument, &i2c, 5}, {"spi_w", no_argument, &i2c, 6}, {"spispeed", required_argument, 0, 'D'}, {"support", no_argument, &support, 1}, {"use_BKosccal", no_argument, &use_BKosccal, 1}, {"version", no_argument, &ver, 1}, {"v", no_argument, &ver, 1}, {"vid", required_argument, 0, 'V'}, {"w", required_argument, 0, 'w'}, {"write", required_argument, 0, 'w'}, {"we", required_argument, 0, 'W'}, {"writeEE", required_argument, 0, 'W'}, {0, 0, 0, 0} }; while ((c = getopt_long_only (argc, argv, "",long_options,&option_index)) != -1) /*{ printf("optarg=%X\n",optarg); if(optarg) printf("%s\n",optarg); printf("c=%X %c\noption_index=%d name=%s\n",c,c,option_index,long_options[option_index].name); } exit(0);*/ switch (c) { case '1': //force config word 1 i=sscanf(optarg, "%x", &cw1); if(i!=1||cw1<0||cw1>0x3FFF) cw1=0x10000; break; case '2': //force config word 2 i=sscanf(optarg, "%x", &cw2); if(i!=1||cw2<0||cw2>0x3FFF) cw2=0x10000; break; case '3': //force config word 3 i=sscanf(optarg, "%x", &cw3); if(i!=1||cw3<0||cw3>0x3FFF) cw3=0x10000; break; case '4': //force config word 4 i=sscanf(optarg, "%x", &cw4); if(i!=1||cw4<0||cw4>0x3FFF) cw4=0x10000; break; case '5': //force config word 5 i=sscanf(optarg, "%x", &cw5); if(i!=1||cw5<0||cw5>0x3FFF) cw5=0x10000; break; case '6': //force config word 6 i=sscanf(optarg, "%x", &cw6); if(i!=1||cw6<0||cw6>0x3FFF) cw6=0x10000; break; case '7': //force config word 7 i=sscanf(optarg, "%x", &cw7); if(i!=1||cw7<0||cw7>0x3FFF) cw7=0x10000; break; case 'd': //device strncpy(dev,optarg,sizeof(dev)-1); break; case 'e': //max write errors max_err = atoi(optarg); break; case 'D': //spi speed spi_speed = atoi(optarg); if(spi_speed<0)spi_speed=0; if(spi_speed>3)spi_speed=3; break; case 'f': //Atmel FUSE low i=sscanf(optarg, "%x", &AVRfuse); if(i!=1||AVRfuse<0||AVRfuse>0xFF) AVRfuse=0x100; break; case 'F': //Atmel FUSE high i=sscanf(optarg, "%x", &AVRfuse_h); if(i!=1||AVRfuse_h<0||AVRfuse_h>0xFF) AVRfuse_h=0x100; break; case 'I': //ICD routine address i=sscanf(optarg, "%x", &ICDaddr); if(i!=1||ICDaddr<0||ICDaddr>0xFFFF) ICDaddr=0x1F00; ICDenable=1; break; case 'k': //Atmel FUSE low @ 3kHz i=sscanf(optarg, "%x", &AVRfuse); if(i!=1||AVRfuse<0||AVRfuse>0xFF) AVRfuse=0x100; else fuse3k=1; break; case 'l': //save Log saveLog=1; if(optarg) strncpy(LogFileName,optarg,sizeof(LogFileName)); break; case 'L': //Atmel LOCK i=sscanf(optarg, "%x", &AVRlock); if(i!=1||AVRlock<0||AVRlock>0xFF) AVRlock=0x100; break; case 'm': //SPI mode spi_mode = atoi(optarg); if(spi_mode<0) spi_mode=0; if(spi_mode>3) spi_mode=3; break; case 'n': //language strncpy(lang,optarg,sizeof(lang)-1); break; #if !defined _WIN32 && !defined __CYGWIN__ case 'p': //hiddev path strncpy(path,optarg,sizeof(path)-1); break; #endif case 'P': //pid sscanf(optarg, "%x", &pid); break; case 'R': //USB HID report size //DIMBUF = atoi(optarg); break; case 's': //save strncpy(savefile,optarg,sizeof(savefile)-1); break; case 'S': //save EE strncpy(savefileEE,optarg,sizeof(savefileEE)-1); break; case 'V': //vid sscanf(optarg, "%x", &vid); break; case 'X': //Atmel extended FUSE i=sscanf(optarg, "%x", &AVRfuse_x); if(i!=1||AVRfuse_x<0||AVRfuse_x>0xFF) AVRfuse_x=0x100; break; case 'w': //write file strncpy(loadfile,optarg,sizeof(loadfile)-1); break; case 'W': //write EE file strncpy(loadfileEE,optarg,sizeof(loadfileEE)-1); break; case '?': fprintf (stderr,strings[L_OPTERR]); //errore opzioni return 1; default: break; } for(j=0,i = optind; i < argc&&i<128; i++,j++) sscanf(argv[i], "%x", &tmpbuf[j]); for(;j<128;j++) tmpbuf[j]=0; strinit(); i=0; if(lang[0]){ //explicit language selection if(lang[0]=='i'&&langid[1]=='t'){ //built-in strings=strings_it; i=1; } else if(lang[0]=='e'&&lang[1]=='n'){ //built-in strings=strings_en; i=1; } else i=strfind(lang,"languages.rc"); //file look-up } if(i==0){ #if defined _WIN32 langid=malloc(19); int n=GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SISO639LANGNAME,langid,9); langid[n-1] = '-'; GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SISO3166CTRYNAME,langid+n, 9); //printf("%d >%s<\n",n,langid); #else langid=getenv("LANG"); #endif if(langid){ if(langid[0]=='i'&&langid[1]=='t') strings=strings_it; else if(langid[0]=='e'&&langid[1]=='n') strings=strings_en; else if(strfind(langid,"languages.rc")); //first try full code else { //then only first language code char* p=strchr(langid,'-'); if(p) *p=0; if(!strfind(langid,"languages.rc")) strings=strings_en; } } else strings=strings_en; } strncpy(LogFileName,strings[S_LogFile],sizeof(LogFileName)); if(argc==1){ printf("OP v%s\n",VERSION); printf(strings[L_HELP]); exit(1); } if(help){ printf(strings[L_HELP]); return 1; } if(langfile) GenerateLangFile(langid,"languages.rc"); if (ver){ printf("OP v%s\nCopyright (C) Alberto Maccioni 2009-2023\ \n For detailed info see http://openprog.altervista.org/\ \nThis 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.\ \n",VERSION); return 0; } if (support){ char list[20000]; //make sure list is long enough!! AddDevices(list); printf("%s\n",list); return 0; } DeviceDetected=FindDevice(vid,pid); //connect to USB programmer if(!DeviceDetected){ DeviceDetected=FindDevice(new_vid,new_pid); //try default if(DeviceDetected){ vid=new_vid; pid=new_pid; } } if(!DeviceDetected) DeviceDetected=FindDevice(old_vid,old_pid); //try old one if(!DeviceDetected) exit(1); ProgID(); //get firmware version and reset #if !defined _WIN32 && !defined __CYGWIN__ if(info){ #ifndef hiddevIO //use raw USB device struct hidraw_devinfo device_info; char name[256],path[256]; ioctl(fd, HIDIOCGRAWINFO, &device_info); ioctl(fd, HIDIOCGRAWNAME(256), name); ioctl(fd, HIDIOCGRAWPHYS(256), path); printf("VID 0x%04X PID 0x%04X\n",device_info.vendor, device_info.product); printf(strings[L_NAME], path, name);//"The device on %s says its name is %s\n" #else //use hiddev device (old method) struct hiddev_devinfo device_info; ioctl(fd, HIDIOCGDEVINFO, &device_info); printf(strings[L_INFO1],device_info.vendor, device_info.product, device_info.version); printf(strings[L_INFO2],device_info.busnum, device_info.devnum, device_info.ifnum); char name[256]; strcpy(name,strings[L_UNKNOWN]);//"Unknown" if(ioctl(fd, HIDIOCGNAME(sizeof(name)), name) < 0) perror("evdev ioctl"); printf(strings[L_NAME], path, name);//"The device on %s says its name is %s\n" #endif return 0; } #endif DWORD t0,t; t=t0=GetTickCount(); if(testhw){ TestHw(); return 0; } if(command){ //bufferU[0]=0; for(i=0;i "); for(i=0;i0x8008){ //16F1xxx if(cw1<=0x3FFF){ memCODE_W[0x8007]=cw1; PrintMessage3(strings[S_ForceConfigWx],1,0x8007,cw1); //"forcing config word%d [0x%04X]=0x%04X" } if(cw2<=0x3FFF){ memCODE_W[0x8008]=cw2; PrintMessage3(strings[S_ForceConfigWx],2,0x8008,cw2); //"forcing config word%d [0x%04X]=0x%04X" } } else{ //16Fxxx if(cw1<=0x3FFF&&sizeW>0x2007){ memCODE_W[0x2007]=cw1; PrintMessage3(strings[S_ForceConfigWx],1,0x2007,cw1); //"forcing config word%d [0x%04X]=0x%04X" } if(cw2<=0x3FFF&&sizeW>0x2008){ memCODE_W[0x2008]=cw2; printf("2\n"); PrintMessage3(strings[S_ForceConfigWx],2,0x2008,cw2); //"forcing config word%d [0x%04X]=0x%04X" } } } else if(devType==PIC12){ //12Fxxx if(cw1<=0xFFF&&sizeW>0xFFF){ memCODE_W[0xFFF]=cw1; PrintMessage3(strings[S_ForceConfigWx],1,0xFFF,cw1); //"forcing config word%d [0x%04X]=0x%04X" } } else if(devType==PIC18){ //18Fxxx if(cw1<=0xFFFF){ memCONFIG[0]=cw1&0xFF; memCONFIG[1]=(cw1>>8)&0xFF; } if(cw2<=0xFFFF){ memCONFIG[2]=cw2&0xFF; memCONFIG[3]=(cw2>>8)&0xFF; } if(cw3<=0xFFFF){ memCONFIG[4]=cw3&0xFF; memCONFIG[5]=(cw3>>8)&0xFF; } if(cw4<=0xFFFF){ memCONFIG[6]=cw4&0xFF; memCONFIG[7]=(cw4>>8)&0xFF; } if(cw5<=0xFFFF){ memCONFIG[8]=cw5&0xFF; memCONFIG[9]=(cw5>>8)&0xFF; } if(cw6<=0xFFFF){ memCONFIG[10]=cw6&0xFF; memCONFIG[11]=(cw6>>8)&0xFF; } if(cw7<=0xFFFF){ memCONFIG[12]=cw7&0xFF; memCONFIG[13]=(cw7>>8)&0xFF; } PrintMessage(strings[S_ForceConfigW]); //"forcing config words" 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" } } /* if(CW1_force!=-1||CW2_force!=-1){ if((!strncmp(dev,"16F1",4)||!strncmp(dev,"12F1",4))){ //16F1xxx if(CW1_force!=-1&&sizeW>0x8007) memCODE_W[0x8007]=CW1_force; if(CW2_force!=-1&&sizeW>0x8008) memCODE_W[0x8008]=CW2_force; } else if((!strncmp(dev,"16F",3)||!strncmp(dev,"12F6",4))&&strncmp(dev,"16F5",4)){ //16Fxxx if(CW1_force!=-1&&sizeW>0x2007) memCODE_W[0x2007]=CW1_force; if(CW2_force!=-1&&sizeW>0x2008) memCODE_W[0x2008]=CW2_force; } else if((!strncmp(dev,"12F",3)||!strncmp(dev,"10F",3)||!strncmp(dev,"16F5",4))){ //12Fxxx if(CW1_force!=-1&&sizeW>0xFFF) memCODE_W[0xFFF]=CW1_force&0xFFF; } if(CW1_force!=-1) PrintMessage1(strings[S_ForceConfigWx],CW1_force); //"forcing config word1 (0x%04X)" if(CW2_force!=-1) PrintMessage1(strings[S_ForceConfigWx],CW2_force); //"forcing config word2 (0x%04X)" } */ //Start with button if(s1){ PrintMessage(strings[S_WaitS1W]); //"Press S1 to program, any key to exit" fflush(stdout); for(;!kbhit();msDelay(50)){ if(CheckS1()){ //wait for S1 Write(dev,ee); //choose the right function PrintMessage(strings[S_WaitS1W]); //"Press S1 to program, any key to exit" fflush(stdout); for(;CheckS1();msDelay(50)); //wait for S1 open } } getch(); } else Write(dev,ee); //choose the right function } else{ //read if(s1){ PrintMessage(strings[S_WaitS1R]); //"Press S1 to read, any key to exit" fflush(stdout); for(;!kbhit();msDelay(50)){ if(CheckS1()){ //wait for S1 Read(dev,ee,r); //choose the right function PrintMessage(strings[S_WaitS1R]); //"Press S1 to read, any key to exit" fflush(stdout); for(;CheckS1();msDelay(50)); //wait for S1 open } } getch(); } else Read(dev,ee,r); //choose the right function if(savefile[0]) Save(dev,savefile); if(!strncmp(dev,"AT",2)&&savefileEE[0]) SaveEE(dev,savefileEE); } #if !defined _WIN32 && !defined __CYGWIN__ //Linux close(fd); #endif return 0 ; } /// ///Display contents of EEprom memory void DisplayEE(){ char s[256],t[256],v[256]; int valid=0,empty=1; int i,j; s[0]=0; v[0]=0; PrintMessage(strings[S_EEMem]); //"\r\nmemoria EEPROM:\r\n" for(i=0;i