/**
* \file opgui.c
* main control program for the open programmer
*
* Copyright (C) 2009-2023 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 "coff.h"
#include "icd.h"
#include "deviceRW.h"
#include "fileIO.h"
#include "progAVR.h"
#define MAXLINES 600
#define CONFIG_FILE "opgui.ini"
#define CONFIG_DIR ".opgui"
void Connect(GtkWidget *widget,GtkWidget *window);
void Quit(GtkWidget *widget,GtkWidget *window) { gtk_main_quit(); }
void I2cspiR();
void I2cspiS();
void PrintMessageI2C(const char *msg);
void ShowContext();
int FindDevice(int vid,int pid);
void TestHw();
int cmdline=0;
int vid=0x1209,pid=0x5432;
int DeviceDetected=0;
int IOTimer=0;
int skipV33check=0;
int waitS1=0,waitingS1=0;
int progress=0;
#ifdef DEBUG
int addrDebug=0;
unsigned short dataDebug=0;
unsigned short statusDebug=0x3FFF;
#endif
//List of gtk controls
GtkTextBuffer * dataBuf;
GtkWidget * data,*data_scroll;
GtkWidget * window;
GtkWidget * toolbar;
GtkWidget * button;
GtkWidget * b_open;
GtkWidget * b_save;
GtkWidget * b_read;
GtkWidget * b_write;
GtkWidget * notebook;
GtkWidget * label;
GtkWidget * status_bar;
GtkWidget * img;
GtkWidget * devTree;
GtkWidget * devTypeCombo;
GtkWidget * devFramePIC;
GtkWidget * ICD_check;
GtkWidget * ICD_addr_entry;
GtkWidget * EEPROM_RW;
GtkWidget * ReadReserved;
GtkWidget * Write_ID_BKCal;
GtkWidget * WriteCalib12;
GtkWidget * UseOSCCAL;
GtkWidget * UseBKOSCCAL;
GtkWidget * UseFileCal;
GtkWidget * devFrameAVR;
GtkWidget * AVR_FuseLow,* AVR_FuseLowWrite,* AVR_FuseHigh,* AVR_FuseHighWrite,* AVR_FuseExt;
GtkWidget * AVR_FuseExtWrite,* AVR_Lock,* AVR_LockWrite;
GtkWidget * b_WfuseLF;
GtkWidget * b_connect;
GtkWidget * b_testhw;
GtkWidget * b_log;
GtkWidget * VID_entry;
GtkWidget * PID_entry;
GtkWidget * Errors_entry;
GtkWidget * I2C8bit;
GtkWidget * I2C16bit;
GtkWidget * SPI00;
GtkWidget * SPI01;
GtkWidget * SPI10;
GtkWidget * SPI11;
GtkWidget * I2CDataSend;
GtkWidget * I2CDataReceive;
GtkWidget * I2CSendBtn;
GtkWidget * I2CReceiveBtn;
GtkWidget * I2CNbyte;
GtkWidget * I2CSpeed;
GtkWidget * DCDC_ON;
GtkWidget * DCDC_voltage;
GtkWidget * VPP_ON;
GtkWidget * VDD_ON;
GtkWidget * b_io_active;
GtkWidget * commandSend;
GtkWidget * commandTransfer;
GtkWidget * b_V33check;
GtkWidget * Hex_entry;
GtkWidget * Address_entry;
GtkWidget * Data_entry;
GtkWidget * Hex_data;
GtkWidget * Hex_data2;
GtkWidget * CW1_entry;
GtkWidget * CW2_entry;
GtkWidget * CW3_entry;
GtkWidget * CW4_entry;
GtkWidget * CW5_entry;
GtkWidget * CW6_entry;
GtkWidget * CW7_entry;
GtkWidget * ConfigForce;
GtkWidget * b_WaitS1;
GtkWidget * devFrameConfigW;
GtkWidget * devFrameICD;
GtkWidget * devFrameOsc;
GtkWidget * devPIC_CW1;
GtkWidget * devPIC_CW2;
GtkWidget * devPIC_CW3;
GtkWidget * devPIC_CW4;
GtkWidget * devPIC_CW5;
GtkWidget * devPIC_CW6;
GtkWidget * devPIC_CW7;
GtkWidget * devPIC_CW8;
GtkWidget * devinfo;
GtkWidget* stopBtn;
GtkWidget* readBtn;
GtkWidget* writeBtn;
GtkListStore *devStore;
GtkWidget *devTree, *devFiltEntry, *devFrame;
GtkTreeSelection *devSel;
///array of radio buttons for IO manual control
struct io_btn { char * name;
int x;
int y;
GtkWidget * r_0; //radio button 0
GtkWidget * r_1; //radio button 1
GtkWidget * r_I; //radio button I
GtkWidget * e_I; //entry
} ioButtons[13];
int statusID;
int ee = 0;
int readRes=0;
char dev[64]="";
int devType=-1;
char* cur_path=0;
char* cur_pathEE=0;
enum dev_column_t {
DEVICE_ID_COLUMN = 0,
DEVICE_NAME_COLUMN,
DEVICE_GROUP_COLUMN,
DEVICE_N_COLUMNS
};
enum sort_type_t {
SORT_STRING_NAME = 0,
SORT_STRING_GROUP
};
enum sort_data_type_t { SDT_STRING = 0 };
char *groupNames[NUM_GROUPS] = {
"PIC10/12",
"PIC16",
"PIC18",
"PIC24",
"PIC30/33",
"ATMEL AVR",
"MEMORY"
};
char *GROUP_ALL="*";
///
///Exit
gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data )
{
gtk_main_quit ();
return FALSE;
}
///
///Show program info window
void info(GtkWidget *widget,GtkWidget *window)
{
const gchar *license =
"This program is free software; you can redistribute it and/or\n"
"modify it under the terms of the GNU Library General Public License as\n"
"published by the Free Software Foundation; either version 2 of the\n"
"License, or (at your option) any later version.\n"
"\n"
"This program is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
"Library General Public License for more details.\n"
"\n"
"You should have received a copy of the GNU Library General Public\n"
"License along with the Gnome Library; see the file COPYING.LIB. If not,\n"
"write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
"Boston, MA 02111-1307, USA.\n";
gtk_show_about_dialog (NULL,
//"artists" GStrv* : Read / Write
//"authors" GStrv* : Read / Write
//"authors","Alberto Maccioni",NULL,
"comments", "A graphical interface for the Open Programmer",
"copyright",
"Copyright (C) Alberto Maccioni 2009-2023\n\n"
"This program is free software; you can \n"
"redistribute it and/or modify it under \n"
"the terms of the GNU General Public License \n"
"as published by the Free Software Foundation;\n"
"either version 2 of the License, or \n"
"(at your option) any later version.",
//"documenters" GStrv* : Read / Write
"license",license,
"logo",gdk_pixbuf_new_from_resource("/res/sys.png", NULL),
// "logo-icon-name" gchar* : Read / Write
"program-name", "OPGUI",
// "translator-credits" gchar* : Read / Write
"version",VERSION,
"website","www.openprog.altervista.org",
// "website-label" gchar* : Read / Write
"wrap-license",TRUE,
"title","Info about OPGUI",
NULL);
}
///
///Append a message on the data tab; shorten the length of the entry field to MAXLINES
void PrintMessage(const char *msg){
if(cmdline) return; //do not print anything if using command line mode
GtkTextIter iter,iter2;
gtk_text_buffer_get_end_iter(dataBuf,&iter);
gtk_text_buffer_insert(dataBuf,&iter,msg,-1);
gtk_text_buffer_get_start_iter(dataBuf,&iter2);
gtk_text_buffer_get_end_iter(dataBuf,&iter);
int l=gtk_text_buffer_get_line_count(dataBuf);
if(l>MAXLINES+10){ //MAXLINES
gtk_text_iter_set_line(&iter,l-MAXLINES);
gtk_text_buffer_delete(dataBuf,&iter2,&iter);
}
while (gtk_events_pending ()) gtk_main_iteration();
gtk_text_buffer_get_end_iter(dataBuf,&iter);
gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(data),&iter,0.0,FALSE,0,0);
}
///
///Print a message on the I2C data field
void PrintMessageI2C(const char *msg){
GtkTextIter iter;
GtkTextBuffer * dataBuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(I2CDataReceive));
gtk_text_buffer_set_text(dataBuf,msg,-1);
gtk_text_buffer_get_end_iter(dataBuf,&iter);
gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(I2CDataReceive),&iter,0.0,FALSE,0,0);
while (gtk_events_pending ()) gtk_main_iteration();
}
///
///Print a message on the "command" data field
void PrintMessageCMD(const char *msg){
GtkTextIter iter;
GtkTextBuffer * dataBuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(commandTransfer));
gtk_text_buffer_set_text(dataBuf,msg,-1);
gtk_text_buffer_get_end_iter(dataBuf,&iter);
gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(commandTransfer),&iter,0.0,FALSE,0,0);
}
///
///Update option variables according to actual control values
void getOptions()
{
vid=htoi(gtk_entry_get_text(GTK_ENTRY(VID_entry)),4);
pid=htoi(gtk_entry_get_text(GTK_ENTRY(PID_entry)),4);
saveLog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_log));
ee = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(EEPROM_RW))?0xFFFF:0;
programID = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Write_ID_BKCal));
max_err=atoi(gtk_entry_get_text(GTK_ENTRY(Errors_entry)));
load_calibword= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(WriteCalib12));
load_osccal= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(UseOSCCAL));
load_BKosccal= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(UseBKOSCCAL));
ICDenable= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ICD_check));
readRes= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ReadReserved));
skipV33check=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_V33check));
waitS1=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_WaitS1));
int i=sscanf(gtk_entry_get_text(GTK_ENTRY(ICD_addr_entry)),"%x",&ICDaddr);
if(i!=1||ICDaddr<0||ICDaddr>0xFFFF) ICDaddr=0x1FF0;
char *str=0;//gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(devCombo));
if(str) strncpy(dev,str,sizeof(dev)-1);
g_free(str);
AVRfuse=AVRfuse_h=AVRfuse_x=AVRlock=0x100;
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(AVR_FuseLowWrite))){
i=sscanf(gtk_entry_get_text(GTK_ENTRY(AVR_FuseLow)),"%x",&AVRfuse);
if(i!=1||AVRfuse<0||AVRfuse>0xFF) AVRfuse=0x100;
}
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(AVR_FuseHighWrite))){
i=sscanf(gtk_entry_get_text(GTK_ENTRY(AVR_FuseHigh)),"%x",&AVRfuse_h);
if(i!=1||AVRfuse_h<0||AVRfuse_h>0xFF) AVRfuse_h=0x100;
}
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(AVR_FuseExtWrite))){
i=sscanf(gtk_entry_get_text(GTK_ENTRY(AVR_FuseExt)),"%x",&AVRfuse_x);
if(i!=1||AVRfuse_x<0||AVRfuse_x>0xFF) AVRfuse_x=0x100;
}
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(AVR_LockWrite))){
i=sscanf(gtk_entry_get_text(GTK_ENTRY(AVR_Lock)),"%x",&AVRlock);
if(i!=1||AVRlock<0||AVRlock>0xFF) AVRlock=0x100;
}
str=malloc(128);
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ConfigForce))){
int cw1,cw2,cw3,cw4,cw5,cw6,cw7;
cw1=cw2=cw3=cw4=cw5=cw6=cw7=0x10000;
i=sscanf(gtk_entry_get_text(GTK_ENTRY(CW1_entry)),"%x",&cw1);
i=sscanf(gtk_entry_get_text(GTK_ENTRY(CW2_entry)),"%x",&cw2);
i=sscanf(gtk_entry_get_text(GTK_ENTRY(CW3_entry)),"%x",&cw3);
i=sscanf(gtk_entry_get_text(GTK_ENTRY(CW4_entry)),"%x",&cw4);
i=sscanf(gtk_entry_get_text(GTK_ENTRY(CW5_entry)),"%x",&cw5);
i=sscanf(gtk_entry_get_text(GTK_ENTRY(CW6_entry)),"%x",&cw6);
i=sscanf(gtk_entry_get_text(GTK_ENTRY(CW7_entry)),"%x",&cw7);
if(devType==PIC16){
if((!strncmp(dev,"16F1",4)||!strncmp(dev,"12F1",4))&&sizeW>0x8008){ //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"
}
}
}
free(str);
}
///
///Check GUI for selected device and put in variable 'dev'. Also enable/disable R/W buttons
void GetSelectedDevice() {
GtkTreeModel *tmpModel;
GtkTreeIter tmpIter;
char *devName;
if (!GTK_IS_TREE_SELECTION(devSel)) { // Not initialised yet
return;
}
if (gtk_tree_selection_get_selected(devSel, &tmpModel, &tmpIter)) {
gtk_tree_model_get(tmpModel, &tmpIter, DEVICE_NAME_COLUMN, &devName, -1);
strcpy(dev,devName);
gtk_widget_set_sensitive(GTK_WIDGET(readBtn), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(writeBtn), TRUE);
g_free(devName);
} else { // Shouldn't ever happen, but just in case
dev[0] = '\0';
gtk_widget_set_sensitive(GTK_WIDGET(readBtn), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(writeBtn), FALSE);
}
}
///
///Choose a file to open and call Load()
void Fopen(GtkWidget *widget,GtkWidget *window)
{
GetSelectedDevice();
if(progress) return;
progress=1;
GtkFileChooser *dialog;
dialog = (GtkFileChooser*) gtk_file_chooser_dialog_new (strings[I_Fopen], //"Open File"
GTK_WINDOW(window),
GTK_FILE_CHOOSER_ACTION_OPEN,
strings[I_CANCEL], GTK_RESPONSE_CANCEL,
strings[I_OPEN], GTK_RESPONSE_ACCEPT,
NULL);
if(cur_path) gtk_file_chooser_set_current_folder(dialog,cur_path);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT){
char *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if(cur_path) free(cur_path);
cur_path = gtk_file_chooser_get_current_folder(dialog);
Load(dev,filename);
g_free (filename);
if(!strncmp(dev,"AT",2)){ //load EEPROM from separate file for ATMEL chips
GtkFileChooser *dialog2;
dialog2 = (GtkFileChooser*) gtk_file_chooser_dialog_new (strings[S_openEEfile],
GTK_WINDOW(window),
GTK_FILE_CHOOSER_ACTION_OPEN,
strings[I_CANCEL],GTK_RESPONSE_CANCEL,
strings[I_OPEN],GTK_RESPONSE_ACCEPT,
NULL);
if(!cur_pathEE) cur_pathEE = gtk_file_chooser_get_current_folder(dialog);
if(cur_pathEE) gtk_file_chooser_set_current_folder(dialog2,cur_pathEE);
if (gtk_dialog_run (GTK_DIALOG (dialog2)) == GTK_RESPONSE_ACCEPT){
char *filename2;
filename2 = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog2));
if(cur_pathEE) free(cur_pathEE);
cur_pathEE = gtk_file_chooser_get_current_folder(dialog2);
LoadEE(dev,filename2);
g_free (filename2);
}
gtk_widget_destroy(GTK_WIDGET(dialog2));
}
}
gtk_widget_destroy (GTK_WIDGET(dialog));
progress=0;
}
///
///Choose a file to save and call Save()
void Fsave(GtkWidget *widget,GtkWidget *window)
{
if(progress) return;
progress=1;
GtkFileChooser *dialog;
dialog = (GtkFileChooser*) gtk_file_chooser_dialog_new (strings[I_Fsave], //"Save File",
GTK_WINDOW(window),
GTK_FILE_CHOOSER_ACTION_SAVE,
strings[I_CANCEL], GTK_RESPONSE_CANCEL,
strings[I_SAVE], GTK_RESPONSE_ACCEPT,
NULL);
if(cur_path) gtk_file_chooser_set_current_folder(dialog,cur_path);
gtk_file_chooser_set_do_overwrite_confirmation(dialog,TRUE);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if(cur_path) free(cur_path);
cur_path = gtk_file_chooser_get_current_folder(dialog);
Save(dev,filename);
PrintMessage1(strings[S_FileSaved],filename);
g_free (filename);
if(!strncmp(dev,"AT",2)&&sizeEE){ //save EEPROM on separate file for ATMEL chips
GtkFileChooser *dialog2;
dialog2 = (GtkFileChooser*) gtk_file_chooser_dialog_new (strings[S_saveEEfile],
GTK_WINDOW(window),
GTK_FILE_CHOOSER_ACTION_SAVE,
strings[I_CANCEL], GTK_RESPONSE_CANCEL,
strings[I_SAVE], GTK_RESPONSE_ACCEPT,
NULL);
if(!cur_pathEE) cur_pathEE = gtk_file_chooser_get_current_folder(dialog);
if(cur_pathEE) gtk_file_chooser_set_current_folder(dialog2,cur_pathEE);
gtk_file_chooser_set_do_overwrite_confirmation(dialog2,TRUE);
if (gtk_dialog_run (GTK_DIALOG (dialog2)) == GTK_RESPONSE_ACCEPT){
char *filename2;
filename2 = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog2));
if(cur_pathEE) free(cur_pathEE);
cur_pathEE = gtk_file_chooser_get_current_folder(dialog2);
SaveEE(dev,filename2);
PrintMessage1(strings[S_FileSaved],filename2);
g_free (filename2);
}
gtk_widget_destroy(GTK_WIDGET(dialog2));
}
}
gtk_widget_destroy (GTK_WIDGET(dialog));
progress=0;
}
///
///Select data tab
void selectDataTab() { gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0); }
///
///Call device write function
void DevWrite(GtkWidget *widget,GtkWidget *window)
{
#ifndef DEBUG
if(DeviceDetected!=1) return;
#endif
selectDataTab();
gtk_statusbar_push(GTK_STATUSBAR(status_bar),statusID,"");
RWstop=0;
getOptions();
if(!waitingS1&&waitS1){
waitingS1=1;
int i,S1=0;
PrintMessage(strings[I_PRESSS1]); //"press S1 to start"
for(i=0;!S1&&waitS1&&waitingS1;i++){
S1=CheckS1();
msDelay(50);
PrintMessage(".");
if(i%64==63) PrintMessage(strings[S_NL]); //"\n"
while (gtk_events_pending ()) gtk_main_iteration(); //handle UI events, including write button
msDelay(50);
}
PrintMessage(strings[S_NL]); //"\n"
if(!progress&&S1){
gtk_widget_set_sensitive(stopBtn,TRUE);
progress=1;
Write(dev,ee); //choose the right function
progress=0;
gtk_widget_set_sensitive(stopBtn,FALSE);
}
waitingS1=0;
}
else if(waitingS1) waitingS1=0;
else if(!progress){
gtk_widget_set_sensitive(stopBtn,TRUE);
progress=1;
Write(dev,ee); //choose the right function
progress=0;
gtk_widget_set_sensitive(stopBtn,FALSE);
}
}
///
///Call device read function
void DevRead(GtkWidget *widget,GtkWidget *window)
{
#ifndef DEBUG
if(DeviceDetected!=1) return;
#endif
selectDataTab();
gtk_statusbar_push(GTK_STATUSBAR(status_bar),statusID,"");
getOptions();
RWstop=0;
if(!waitingS1&&waitS1){
waitingS1=1;
int i,S1=0;
PrintMessage(strings[I_PRESSS1]); //"press S1 to start"
for(i=0;!S1&&waitS1&&waitingS1;i++){
S1=CheckS1();
msDelay(50);
PrintMessage(".");
if(i%64==63) PrintMessage(strings[S_NL]); //"\n"
while (gtk_events_pending ()) gtk_main_iteration(); //handle UI events, including write button
msDelay(50);
}
PrintMessage(strings[S_NL]); //"\n"
if(!progress&&S1){
gtk_widget_set_sensitive(stopBtn,TRUE);
progress=1;
Read(dev,ee,readRes); //choose the right function
progress=0;
gtk_widget_set_sensitive(stopBtn,FALSE);
}
waitingS1=0;
}
else if(waitingS1) waitingS1=0;
else if(!progress){
gtk_widget_set_sensitive(stopBtn,TRUE);
progress=1;
Read(dev,ee,readRes); //choose the right function
progress=0;
gtk_widget_set_sensitive(stopBtn,FALSE);
}
}
///
/// Write fuse low byte at low frequency
void WriteATfuseLowLF(GtkWidget *widget,GtkWidget *window){
#ifndef DEBUG
if(DeviceDetected!=1) return;
#endif
if(progress) return;
getOptions();
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(AVR_FuseLowWrite))){
progress=1;
if(AVRfuse<0x100) WriteATfuseSlow(AVRfuse);
progress=0;
}
}
///
///Callback function to set available options for each device type
void onDevSel_Changed(GtkWidget *widget,GtkWidget *window)
{
struct DevInfo info;
GetSelectedDevice();
if (strlen(dev) == 0) return; // None selected
info=GetDevInfo(dev);
sprintf(str, "%s: %s", strings[I_Dev], dev);
gtk_label_set_markup(GTK_LABEL(devFrame), str);
devType=info.family;
gtk_label_set_text(GTK_LABEL(devinfo),info.features);
if(devType==PIC12||devType==PIC16||devType==PIC18||devType==PIC24){
gtk_widget_show_all(GTK_WIDGET(devFramePIC));
gtk_widget_hide(GTK_WIDGET(devFrameAVR));
gtk_widget_show_all(GTK_WIDGET(EEPROM_RW));
}
else if(devType==AVR){ //ATMEL
gtk_widget_hide(GTK_WIDGET(devFramePIC));
gtk_widget_show_all(GTK_WIDGET(devFrameAVR));
gtk_widget_show_all(GTK_WIDGET(EEPROM_RW));
}
else{
gtk_widget_hide(GTK_WIDGET(devFramePIC));
gtk_widget_hide(GTK_WIDGET(devFrameAVR));
gtk_widget_hide(GTK_WIDGET(EEPROM_RW));
}
if(devType==PIC16) //ICD
gtk_widget_show_all(GTK_WIDGET(devFrameICD));
else gtk_widget_hide(GTK_WIDGET(devFrameICD));
if(devType==PIC12||devType==PIC16) //Osc options
gtk_widget_show_all(GTK_WIDGET(devFrameOsc));
else gtk_widget_hide(GTK_WIDGET(devFrameOsc));
if(devType==PIC12||devType==PIC16||devType==PIC18) //program ID
gtk_widget_show_all(GTK_WIDGET(Write_ID_BKCal));
else gtk_widget_hide(GTK_WIDGET(Write_ID_BKCal));
if(devType==PIC16) //Program Calib
gtk_widget_show_all(GTK_WIDGET(WriteCalib12));
else gtk_widget_hide(GTK_WIDGET(WriteCalib12));
if(devType==PIC12||devType==PIC16||devType==PIC18){ //Force config
gtk_widget_show_all(GTK_WIDGET(devFrameConfigW));
gtk_widget_hide(GTK_WIDGET(devPIC_CW2));
gtk_widget_hide(GTK_WIDGET(devPIC_CW3));
gtk_widget_hide(GTK_WIDGET(devPIC_CW4));
gtk_widget_hide(GTK_WIDGET(devPIC_CW5));
gtk_widget_hide(GTK_WIDGET(devPIC_CW6));
gtk_widget_hide(GTK_WIDGET(devPIC_CW7));
gtk_widget_hide(GTK_WIDGET(devPIC_CW8));
if(devType==PIC16){
gtk_widget_show_all(GTK_WIDGET(devPIC_CW2));
}
else if(devType==PIC18){
gtk_widget_show_all(GTK_WIDGET(devPIC_CW2));
gtk_widget_show_all(GTK_WIDGET(devPIC_CW3));
gtk_widget_show_all(GTK_WIDGET(devPIC_CW4));
gtk_widget_show_all(GTK_WIDGET(devPIC_CW5));
gtk_widget_show_all(GTK_WIDGET(devPIC_CW6));
gtk_widget_show_all(GTK_WIDGET(devPIC_CW7));
gtk_widget_show_all(GTK_WIDGET(devPIC_CW8));
}
}
else{
gtk_widget_hide(GTK_WIDGET(devFrameConfigW));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ConfigForce),FALSE);
}
gtk_statusbar_push(GTK_STATUSBAR(status_bar),statusID,dev);
}
/// Walk the TreeModel until we find an entry with the passed device name
/// Select that entry and then stop walking
gboolean selectDev_ForeachFunc(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, char *devNameToSelect) {
char *thisEntryDevName;
gtk_tree_model_get(model, iter, DEVICE_NAME_COLUMN, &thisEntryDevName, -1);
int matched = (strcmp(thisEntryDevName, devNameToSelect) == 0);
if (matched) gtk_tree_selection_select_iter(devSel, iter);
g_free(thisEntryDevName);
return matched;
}
///
/// Comparison function used when sorting the device tree
int sortIterCompareFunc(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata) {
enum sort_type_t sortcol = GPOINTER_TO_INT(userdata);
int ret = 0;
enum sort_data_type_t sortDataType;
int dataCol;
switch (sortcol) {
case SORT_STRING_NAME:
sortDataType = SDT_STRING;
dataCol = DEVICE_NAME_COLUMN;
break;
case SORT_STRING_GROUP:
sortDataType = SDT_STRING;
dataCol = DEVICE_GROUP_COLUMN;
break;
default:
return 0;
}
switch (sortDataType) {
case SDT_STRING:
{
char *nameA, *nameB;
gtk_tree_model_get(model, a, dataCol, &nameA, -1);
gtk_tree_model_get(model, b, dataCol, &nameB, -1);
if (nameA == NULL || nameB == NULL) {
if (nameA == NULL && nameB == NULL) break; // Both null. return 0 (no need to free)
ret = (nameA == NULL) ? -1 : 1;
}
else {
ret = g_utf8_collate(nameA,nameB);
}
g_free(nameA);
g_free(nameB);
break;
}
default:
g_return_val_if_reached(0);
}
return ret;
}
#ifndef strupr
char* strupr( char* s ){
char* p = s;
while (*p = toupper( *p )) p++;
return s;
}
#endif
///
///Add devices to the device ListStore (which may not have been created)
///groupFilter: add devices in this group (-1 for all)
///textFilter: only add devices containing this string (NULL for all)
void AddDevices(enum group_t groupFilter, const char *textFilter) {
if (GTK_IS_TREE_SELECTION(devSel))
g_signal_handlers_disconnect_by_func(G_OBJECT(devSel),G_CALLBACK(onDevSel_Changed),NULL);
if (!GTK_IS_LIST_STORE(devStore)) {
devStore = gtk_list_store_new (DEVICE_N_COLUMNS,
G_TYPE_UINT,
G_TYPE_STRING,
G_TYPE_STRING);
gtk_tree_view_set_model(GTK_TREE_VIEW(devTree), GTK_TREE_MODEL(devStore));
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(devStore), SORT_STRING_NAME,
sortIterCompareFunc, GINT_TO_POINTER(SORT_STRING_NAME), NULL);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(devStore), SORT_STRING_GROUP,
sortIterCompareFunc, GINT_TO_POINTER(SORT_STRING_GROUP), NULL);
gtk_tree_view_column_set_sort_column_id(
gtk_tree_view_get_column(GTK_TREE_VIEW(devTree), 0), SORT_STRING_NAME);
gtk_tree_view_column_set_sort_column_id(
gtk_tree_view_get_column(GTK_TREE_VIEW(devTree), 1), SORT_STRING_GROUP);
g_object_unref (G_OBJECT(devStore));
}
else gtk_list_store_clear(devStore);
int i,j=0;
char *devices=0,*tok;
char textFilterU[32];
strupr(strncpy(textFilterU,textFilter,32));
for(i=0;i0){
if(hex[0]==':'&&strlen(hex)>8){
length=htoi(hex+1,2);
address=htoi(hex+3,4);
if(strlen(hex)<11+length*2) gtk_entry_set_text(GTK_ENTRY(Hex_data),"__line too short");
else{
for (i=1;i<=length*2+9;i+=2) sum += htoi(hex+i,2);
if ((sum & 0xff)!=0){
sprintf(str,"__checksum error, expected 0x%02X",(-sum+htoi(hex+9+length*2,2))&0xFF);
gtk_entry_set_text(GTK_ENTRY(Hex_data),str);
}
else{
switch(htoi(hex+7,2)){
case 0: //Data record
sprintf(str,"address: 0x%04X ",address);
if(i&&length) strcat(str,"data: 0x");
for (i=0;i14){
sprintf(str,"extended linear address = %04X",htoi(hex+9,4));
gtk_entry_set_text(GTK_ENTRY(Hex_data),str);
}
break;
default:
gtk_entry_set_text(GTK_ENTRY(Hex_data),"__unknown record type");
break;
}
}
}
}
else gtk_entry_set_text(GTK_ENTRY(Hex_data),"__invalid line");
}
else gtk_entry_set_text(GTK_ENTRY(Hex_entry),"");
}
///
/// convert address & data to hex line
void DataToHexConvert(GtkWidget *widget,GtkWidget *window)
{
char hex[256],str[256],s2[32];
int i,address,length,sum=0,x;
i=sscanf(gtk_entry_get_text(GTK_ENTRY(Address_entry)),"%x",&address);
if(i!=1) address=0;
strncpy(hex,(const char *)gtk_entry_get_text(GTK_ENTRY(Data_entry)),sizeof(hex));
length=strlen(hex);
length&=0xFF;
if(length>0){
sprintf(str,":--%04X00",address&0xFFFF);
for(i=0;i+1>8)&0xff);
sprintf(s2,"%02X",(-sum)&0xFF);
strcat(str,s2);
gtk_entry_set_text(GTK_ENTRY(Hex_data2),str);
}
}
///
///Choose a file to save a hex line
void HexSave(GtkWidget *widget,GtkWidget *window)
{
GtkFileChooser *dialog;
if(strlen((const char *)gtk_entry_get_text(GTK_ENTRY(Hex_data2)))<11) return;
dialog = (GtkFileChooser*) gtk_file_chooser_dialog_new (strings[I_Fsave], //"Save File",
GTK_WINDOW(window),
GTK_FILE_CHOOSER_ACTION_SAVE,
strings[I_CANCEL], GTK_RESPONSE_CANCEL,
strings[I_SAVE], GTK_RESPONSE_ACCEPT,
NULL);
if(cur_path) gtk_file_chooser_set_current_folder(dialog,cur_path);
gtk_file_chooser_set_do_overwrite_confirmation(dialog,TRUE);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if(cur_path) free(cur_path);
cur_path = gtk_file_chooser_get_current_folder(dialog);
FILE* f=fopen(filename,"w");
if(f){
fprintf(f,(const char *)gtk_entry_get_text(GTK_ENTRY(Hex_data2)));
fclose(f);
}
g_free (filename);
}
gtk_widget_destroy (GTK_WIDGET(dialog));
}
///
/// Stop read or write
void Stop(GtkWidget *widget,GtkWidget *window)
{
#ifndef DEBUG
if(DeviceDetected!=1) return;
#endif
if(progress==1&&RWstop==0){
RWstop=1;
PrintMessage(strings[I_STOP]);
}
}
///
///Close program
void Xclose(){
// char *str=gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(devCombo));
// if(str) strncpy(dev,str,sizeof(dev)-1);
gtk_main_quit();
}
///
/// Show a message box
void MsgBox(const char* msg)
{
GtkWidget * dialog = gtk_message_dialog_new (GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
msg);
gtk_window_set_title(GTK_WINDOW(dialog)," ");
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
///
/// Find the programmer and setup communication
void Connect(GtkWidget *widget,GtkWidget *window){
vid=htoi(gtk_entry_get_text(GTK_ENTRY(VID_entry)),4);
pid=htoi(gtk_entry_get_text(GTK_ENTRY(PID_entry)),4);
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
hvreg=0;
ProgID();
}
///
/// I2C/SPI receive
void I2cspiR()
{
//if(DeviceDetected!=1) return;
gtk_statusbar_push(GTK_STATUSBAR(status_bar),statusID,"");
saveLog = (int) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_log));
int nbyte=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(I2CNbyte));
if(nbyte<0) nbyte=0;
if(nbyte>60) nbyte=60;
int mode=0;
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(I2C16bit))) mode=1; //I2C mode
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(SPI00))) mode=2; //SPI mode 00
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(SPI01))) mode=3; //SPI mode 01
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(SPI10))) mode=4; //SPI mode 10
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(SPI11))) mode=5; //SPI mode 11
char* tok;
char tokbuf[512];
BYTE tmpbuf[128];
int i=0,x;
strncpy(tokbuf, (const char *)gtk_entry_get_text(GTK_ENTRY(I2CDataSend)), sizeof(tokbuf));
for(tok=strtok(tokbuf," ");tok&&i<128;tok=strtok(NULL," ")){
if(sscanf(tok,"%x",&x)){
tmpbuf[i] = (BYTE)x;
i++;
}
}
for(;i<128;i++) tmpbuf[i]=0;
I2CReceive(mode,gtk_combo_box_get_active(GTK_COMBO_BOX(I2CSpeed)),nbyte,tmpbuf);
}
///
/// I2C/SPI send
void I2cspiS()
{
//if(DeviceDetected!=1) return;
gtk_statusbar_push(GTK_STATUSBAR(status_bar),statusID,"");
saveLog = (int) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_log));
int nbyte=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(I2CNbyte));
if(nbyte<0) nbyte=0;
if(nbyte>57) nbyte=57;
int mode=0;
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(I2C16bit))) mode=1; //I2C mode
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(SPI00))) mode=2; //SPI mode 00
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(SPI01))) mode=3; //SPI mode 01
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(SPI10))) mode=4; //SPI mode 10
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(SPI11))) mode=5; //SPI mode 11
char* tok;
char tokbuf[512];
BYTE tmpbuf[128];
int i=0,x;
strncpy(tokbuf, (const char *)gtk_entry_get_text(GTK_ENTRY(I2CDataSend)), sizeof(tokbuf));
for(tok=strtok(tokbuf," ");tok&&i<128;tok=strtok(NULL," ")){
if(sscanf(tok,"%x",&x)){
tmpbuf[i] = (BYTE)x;
i++;
}
}
for(;i<128;i++) tmpbuf[i]=0;
I2CSend(mode,gtk_combo_box_get_active(GTK_COMBO_BOX(I2CSpeed)),nbyte,tmpbuf);
}
///
/// send manual command
void CommandIO()
{
if(DeviceDetected!=1) return;
gtk_statusbar_push(GTK_STATUSBAR(status_bar),statusID,"");
saveLog = (int) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_log));
char* tok;
char tokbuf[512],str[16];
int i=0,x;
strncpy(tokbuf, (const char *)gtk_entry_get_text(GTK_ENTRY(commandSend)), sizeof(tokbuf));
for(tok=strtok(tokbuf," ");tok&&i[");
for(i=0;i7000?7000:sizeEE;
for(i=0;i500){ //limit number of lines printed
strcat(aux,"(...)\r\n");
i=max-COL*2;
lines=490;
}
}
s[0]=0;
v[0]=0;
}
if(empty) PrintMessage(strings[S_Empty]); //empty
else{
PrintMessage(aux);
if(sizeEE>max) PrintMessage("(...)\r\n");
}
free(aux);
}
///-----------------------------------
///Main function
///-----------------------------------
int main( int argc, char *argv[])
{
//int langID=GetUserDefaultLangID();
FILE *f;
gchar *homedir,*config_dir,*fname=0;
char lang[32]="";
int langfile=0;
homedir = (gchar *) g_get_home_dir ();
if(homedir){
config_dir=g_build_path(G_DIR_SEPARATOR_S,homedir,CONFIG_DIR, NULL);
if(!g_file_test(config_dir,G_FILE_TEST_IS_DIR))
#if defined _WIN32
mkdir(config_dir);
#else
mkdir(config_dir,0755);
#endif
fname = g_build_path(G_DIR_SEPARATOR_S,config_dir,CONFIG_FILE, NULL);
f=fopen(fname,"r");
if(f){
char temp[256],line[256];
int X;
for(;fgets(line,256,f);){
if(sscanf(line,"device %s",temp)>0) strcpy(dev,temp);
else if(sscanf(line,"vid %X",&X)>0) vid=X;
else if(sscanf(line,"pid %X",&X)>0) pid=X;
else sscanf(line,"maxerr %d",&max_err);
}
fclose(f);
}
}
char dev_ini[64];
strncpy(dev_ini,dev,sizeof(dev_ini));
int vid_ini=vid,pid_ini=pid,max_err_ini=max_err;
vid_ini=vid;
pid_ini=pid;
max_err_ini=max_err;
#if defined _WIN32 || defined __CYGWIN__ //Windows
bufferI=bufferI0+1;
bufferU=bufferU0+1;
bufferI0[0]=0;
bufferU0[0]=0;
#endif
gtk_init(&argc, &argv);
unsigned int tmpbuf[128];
opterr = 0;
int option_index = 0;
int help=0,command=0,i,j;
struct option long_options[] =
{
{"?", no_argument, &help, 1},
{"h", no_argument, &help, 1},
{"help", no_argument, &help, 1},
{"c", no_argument, &command, 1},
{"command", no_argument, &command, 1},
{"lang", required_argument, 0, 'l'},
{"langfile", no_argument, &langfile, 1},
{0, 0, 0, 0}
};
while ((j = getopt_long_only (argc, argv, "",long_options,&option_index)) != -1){
if(j=='l'){ //language
strncpy(lang,optarg,sizeof(lang)-1);
}
}
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();
char* langid=0;
i=0;
if(lang[0]){ //explicit language selection
if(lang[0]=='i'&&lang[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;
}
if(langfile) GenerateLangFile(langid,"languages.rc");
if(help){
printf(strings[I_GUI_CMD_HELP]);
exit(0);
}
if(command){
cmdline=1;
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){
bufferU[0]=0;
for(i=1;i ");
for(i=1;i0) {
struct DevInfo info = GetDevInfo(dev);
gtk_combo_box_set_active_id(GTK_COMBO_BOX(devTypeCombo), groupNames[info.group]);
}
else {
gtk_combo_box_set_active_id(GTK_COMBO_BOX(devTypeCombo), GROUP_ALL);
}
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
ProgID(); //get firmware version and reset
gtk_main();
// printf(ListDevices());
//******Save ini file******
// only if parameters are changed
if(strcmp(dev_ini,dev)||vid_ini!=vid||pid_ini!=pid||max_err_ini!=max_err){
if(homedir){
f=fopen(fname,"w");
if(f){
fprintf(f,"device %s\n",dev);
fprintf(f,"maxerr %d\n",max_err);
fprintf(f,"vid %X\n",vid);
fprintf(f,"pid %X\n",pid);
}
fclose(f);
}
}
return 0;
}