00001 #include <unistd.h>
00002 #include <getopt.h>
00003 #include <string.h>
00004 #include <inttypes.h>
00005
00006 #include "converter.h"
00007
00008 #include <stdio.h>
00009
00010 extern int cdi_programmer(conf_opts_t *conf, char *filename);
00011
00012 void usage(char *prg_name)
00013 {
00014 printf("\nUsage: %s -f ihex file\n", prg_name);
00015 printf("General options:\n");
00016 printf(" -V/--version Get converter version\n");
00017 }
00018
00019 conf_opts_t conf_opts;
00020
00021 static int option_index = 0;
00022
00023 int do_exit = 0;
00024
00025 #define OPTIONS_STRING "Vhf:"
00026
00027 static struct option long_options[] =
00028 {
00029 {"version", 0, NULL, 'V'},
00030 {"file", 1, NULL, 'f'},
00031 {"help", 0, NULL, 'h'},
00032 {0, 0, 0, 0}
00033 };
00034
00035 int parse_opts(int count, char* param[])
00036 {
00037 int opt;
00038 int error=0;
00039
00040 conf_opts.target_type = UNDEFINED;
00041 while ((opt = getopt_long(count, param, OPTIONS_STRING,
00042 long_options, &option_index)) != -1)
00043 {
00044 switch(opt)
00045 {
00046 case 'V':
00047 conf_opts.target_type = VERSION;
00048 break;
00049
00050 case 'h':
00051 conf_opts.target_type = UNDEFINED;
00052 break;
00053
00054 case 'f':
00055 strcpy(conf_opts.ihex_file, optarg);
00056 conf_opts.target_type = CONVERT;
00057 break;
00058 }
00059 }
00060
00061 if (!error && (conf_opts.target_type == CONVERT) )
00062 {
00063 printf("File: %s.\n", conf_opts.ihex_file);
00064 }
00065
00066 return error;
00067 }
00068
00069 int main(int argc, char *argv[])
00070 {
00071 int error = 0;
00072
00073 conf_opts.target_type = 0;
00074
00075
00076 if ( (argc < 1) || (error = parse_opts(argc, argv)) )
00077 {
00078 usage(argv[0]);
00079 if (error < 0) return error;
00080 else return 0;
00081 }
00082
00083 if(conf_opts.target_type == CONVERT)
00084 {
00085 int pages;
00086 int sdcc_file = 0;
00087
00088 FILE *ihex = 0;
00089 unsigned char check = 0;
00090 unsigned long ext_addr=0;
00091 unsigned short int addr=0;
00092 unsigned char page_buffer[128*1024];
00093 unsigned char page_table[64];
00094 unsigned char buffer[256];
00095 int i;
00096 int retval = 0;
00097
00098 bzero(buffer, sizeof(buffer));
00099
00100
00101 memset(page_table, 0, 64);
00102 memset(page_buffer, 0xFF, sizeof(page_buffer));
00103 pages = 0;
00104
00105 ihex = fopen(conf_opts.ihex_file, "rb");
00106 if (ihex == 0)
00107 {
00108 printf("Can't open file.\n");
00109 return -1;
00110 }
00111 error = 0;
00112 while((!error) && ((retval = fscanf(ihex, "%s", buffer)) == 1) )
00113 {
00114 unsigned char data_len = 0;
00115
00116 if (memcmp(&buffer[7], "00", 2) == 0)
00117 {
00118 i=0;
00119 sscanf((char *)&buffer[1], "%2hhx", &data_len);
00120 sscanf((char *)&(buffer[3]),"%4hx", &addr);
00121 while(i<data_len)
00122 {
00123 uint32_t absolute_address = ext_addr+addr+i;
00124
00125 if (page_table[absolute_address/2048] == 0)
00126 {
00127 page_table[absolute_address/2048] = 1;
00128 pages++;
00129 }
00130 sscanf((char *)&buffer[2*i+9], "%2hhx", &page_buffer[absolute_address]);
00131 i++;
00132 }
00133 }
00134 else if (memcmp(&buffer[7], "01", 2) == 0)
00135 {
00136 printf("\nFile read complete.\n");
00137 break;
00138 }
00139 else if (memcmp(&buffer[7], "04", 2) == 0)
00140 {
00141 sscanf((char *)&(buffer[3]),"%4hx", &addr);
00142 sscanf((char *)&(buffer[9]),"%4lx", &ext_addr);
00143 printf("\rExtended page address: 0x%8.8lX\r", ext_addr*0x8000 );
00144
00145 if (ext_addr >= 0x0002) sdcc_file = 1;
00146
00147 if (ext_addr) ext_addr--;
00148 ext_addr *= 0x8000;
00149 }
00150 }
00151 fclose(ihex);
00152 if (retval == -1)
00153 {
00154 printf("Read error\n");
00155 }
00156 if (sdcc_file == 0)
00157 {
00158 printf("Not a SDCC banked file.\n");
00159 return 0;
00160 }
00161 printf("Writing %d pages.\n", pages);
00162 {
00163 char *ptr = strrchr(conf_opts.ihex_file, '.');
00164 if (ptr != NULL)
00165 {
00166 *ptr = 0;
00167 }
00168 }
00169 strcat(conf_opts.ihex_file, "_linear.hex");
00170 printf("Output file: %s.\n", conf_opts.ihex_file);
00171 ihex = fopen(conf_opts.ihex_file, "wb");
00172 ext_addr=0;
00173 addr = 0;
00174 if (pages)
00175 {
00176 int j;
00177 error = 0;
00178 for (i=0; i<64; i++)
00179 {
00180 addr = (i & 0x1F) * 2048;
00181 if ( ((i / 32) * 0x10000) != ext_addr)
00182 {
00183 printf("Ext: %4.4X\n", ((i / 32) * 0x10000));
00184 ext_addr = (i / 32) * 0x10000;
00185 fprintf(ihex, ":02000004%4.4X%2.2X\r\n",
00186 (int)(ext_addr>>16), (int)(0xFA-(ext_addr>>16)));
00187 }
00188
00189 if (page_table[i] != 0)
00190 {
00191 printf("%4.4X", addr & 0xF800);
00192 for (j=0; j<2048; j++)
00193 {
00194 addr =(i & 0x1F) * 2048 + j;
00195 if ((j & 0x1F) == 0)
00196 {
00197 check = 0;
00198 check -= 0x20;
00199 check -= (uint8_t) (addr >> 8);
00200 check -= (uint8_t) (addr);
00201 fprintf(ihex, ":20%4.4X00", (int) addr);
00202 }
00203 fprintf(ihex, "%2.2X", page_buffer[ext_addr+addr]);
00204 check -= page_buffer[ext_addr+addr];
00205 if ((j & 0x1F) == 0x1F)
00206 {
00207 fprintf(ihex, "%2.2X\r\n", check);
00208 }
00209 }
00210 }
00211 if ((i & 0x07) == 0x07) printf("\n");
00212 else printf(" ");
00213 }
00214 fprintf(ihex, ":00000001FF\r\n");
00215 printf("Write complete.\n");
00216 }
00217 fclose(ihex);
00218 }
00219 else if(conf_opts.target_type == UNDEFINED)
00220 {
00221 usage(argv[0]);
00222 }
00223 else
00224 {
00225 printf("\nSensinode hex file converter "CONVERTER_VERSION "\n");
00226 }
00227 return error;
00228 }