fztatCtrl.cpp

00001 /*
00002   F-ZTAT 管理クラス
00003   Satofumi KAMIMURA
00004   $Id$
00005 */
00006 
00007 #include "fztatCtrl.h"
00008 #include <stdio.h>
00009 
00010 
00011 FZTAT_Ctrl::FZTAT_Ctrl(const char* device, long writeBaudrate)
00012   : error_message("no error"), con(NULL), debug_level(0), view_callback(NULL),
00013     con_device(device), write_baudrate(writeBaudrate), mode(NotInitialized) {
00014 
00015   char* level = getenv("DEBUG_VIEW");
00016   if (level) {
00017     debug_level = atoi(level);
00018   }
00019 }
00020 
00021 
00022 FZTAT_Ctrl::~FZTAT_Ctrl(void) {
00023   disconnect();
00024 }
00025 
00026 
00027 const char* FZTAT_Ctrl::what(void) {
00028   return error_message.c_str();
00029 }
00030 
00031 
00032 int FZTAT_Ctrl::connect(long baudrate) {
00033   disconnect();
00034 
00035   con = new SerialDevice;
00036   int ret_value = con->connect(con_device, baudrate);
00037   if (!ret_value) {
00038     error_message = con->what();
00039   }
00040   return ret_value;
00041 }
00042 
00043 
00044 void FZTAT_Ctrl::disconnect(void) {
00045   delete con;
00046   con = NULL;
00047 }
00048 
00049 
00050 bool FZTAT_Ctrl::adjustBaudrate(void) {
00051   if (mode != NotInitialized) {
00052     error_message = "adjustBaudrate() must be called 1st.";
00053     return false;
00054   }
00055   mode = Invalid;
00056   if (debug_level >= 2) {
00057     mode = BaudrateAdjusted;
00058     return true;
00059   }
00060 
00061   // 初期ボーレート合わせ
00062   enum { FirstBaudrate = 9600, SendTimes = 64 };
00063   if (connect(FirstBaudrate) < 0) {
00064     return false;
00065   }
00066 
00067   int i;
00068   char send_ch = 0x00;
00069   for (i = 0; i < SendTimes; ++i) {
00070     for (int j = 0; j < 3; ++j) {
00071       con->send(&send_ch, 1);
00072     }
00073     unsigned char recv_ch = 0xff;
00074     if ((con->recv((char*)&recv_ch, 1, 1) > 0) && (recv_ch == 0x00)) {
00075       break;
00076     }
00077   }
00078   if (i == SendTimes) {
00079     error_message = "no reply! (expected 0x00)";
00080     return false;
00081   }
00082   con->flush();
00083 
00084   send_ch = 0x55;
00085   unsigned char recv_ch = 0xff;
00086   con->send(&send_ch, 1);
00087   int n = con->recv((char*)&recv_ch, 1, Timeout);
00088   if ((n > 0) && (recv_ch == 0xaa)) {
00089     mode = BaudrateAdjusted;
00090     return true;
00091   }
00092 
00093   error_message = "no reply! (expected 0xaa)";
00094   return false;
00095 }
00096 
00097 
00098 bool FZTAT_Ctrl::sendWriteProgram(char* code, int size) {
00099   if (mode != BaudrateAdjusted) {
00100     error_message = "sendWriteProgram() must be called 2nd.";
00101     return false;
00102   }
00103   mode = Invalid;
00104   if (debug_level >= 2) {
00105     mode = ProgramSended;
00106     return true;
00107   }
00108 
00109   // 書き込み制御プログラムのサイズを転送
00110   char size_array[] = { size >> 8, size & 0xff };
00111   con->send(size_array, 2);
00112 
00113   char recv_buffer[2];
00114   int n = con->recv(recv_buffer, 2, Timeout);
00115   if ((n < 2) || strncmp(size_array, recv_buffer, 2)) {
00116     error_message = "send program size: echo back fail!";
00117     return false;
00118   }
00119 
00120   // 書き込み制御プログラムの転送
00121   con->send(code, size);
00122   for (int i = 0; i < size; ++i) {
00123     char echoback_ch;
00124     con->recv(&echoback_ch, 1, Timeout);
00125   }
00126 
00127   if ((con->recv(recv_buffer, 1, Timeout) <= 0) ||
00128       (static_cast<unsigned char>(recv_buffer[0]) != 0xaa)) {
00129     error_message = "no reply! (expected 0xaa)";
00130     return false;
00131   }
00132   con->setBaudrate(write_baudrate);
00133 
00134   mode = ProgramSended;
00135   return true;
00136 }
00137 
00138 
00139 void FZTAT_Ctrl::setProgressCallback(progressView_t func) {
00140   view_callback = func;
00141 }
00142 
00143 
00144 bool FZTAT_Ctrl::isLF(const char ch) {
00145   return ((ch == '\r') || (ch == '\n')) ? true : false;
00146 }
00147 
00148 
00149 long FZTAT_Ctrl::setDataBuffer(char* buffer, SFormat_Ctrl::srec_t* srec) {
00150 
00151   // アドレス情報の配置
00152   long address = srec->address & 0xffffffe0;
00153   buffer[0] = static_cast<char>(address >> 24);
00154   buffer[1] = static_cast<char>(address >> 16);
00155   buffer[2] = static_cast<char>(address >> 8);
00156   buffer[3] = static_cast<char>(address);
00157 
00158   // データ情報の配置
00159   int offset = (srec->address & 0x00000010) ? 16 : 0;
00160   for (int i = 0; i < 16; ++i) {
00161     buffer[4 + offset + i] = srec->byte_data[i];
00162   }
00163 
00164   // チェックサムの生成
00165   char sum = 0;
00166   for (int i = 0; i < 4 + 32; ++i) {
00167     sum += buffer[i];
00168   }
00169   buffer[4 + 32] = sum;
00170 
00171   return address;
00172 }
00173 
00174 
00175 bool FZTAT_Ctrl::fillSendBuffer(int* sended,
00176                                char* buffer, const char* code, int left) {
00177   enum { InvalidAddress = -1 };
00178   long now_address = InvalidAddress;
00179   int index = 0;
00180   bool doSend = false;
00181   memset(buffer, 0, 4 + 32 + 1);
00182 
00183   for (int i = 0; (i < 2) && (index < left); ) {
00184     SFormat_Ctrl::srec_t srec;
00185     int n = SFormat_Ctrl::parseSFormat(&srec, &code[index]);
00186     if (n <= 0) {
00187       *sended = n;
00188       return doSend;
00189     }
00190     if (debug_level > 0) {
00191       for (int j = 0; j < n; ++j) {
00192         fprintf(stderr, "%c", code[index + j]);
00193       }
00194       fprintf(stderr, "\n");
00195     }
00196 
00197     if ((srec.type < 1) || (srec.type > 3)) {
00198       index += n;
00199       continue;
00200     }
00201 
00202     long set_address = srec.address & 0xffffffe0;
00203     if ((now_address != InvalidAddress) && (now_address != set_address)) {
00204       *sended = index;
00205       return doSend;
00206     }
00207     now_address = setDataBuffer(buffer, &srec);
00208     index += n;
00209     doSend = true;
00210 
00211     ++i;
00212   }
00213   *sended = index;
00214   return doSend;
00215 }
00216 
00217 
00218 bool FZTAT_Ctrl::writeRom(char* code, int size, long baudrate) {
00219   if (mode != ProgramSended) {
00220     error_message = "writeRom() must be called 3rd.";
00221     return false;
00222   }
00223   mode = Invalid;
00224 
00225   // 書き込み時のボーレートを設定
00226   char send_buffer[LineMax];
00227   sprintf(send_buffer, "S%ld\n", write_baudrate);
00228   int len = strlen(send_buffer);
00229   if (debug_level > 0) {
00230     fprintf(stderr, "%s", send_buffer);
00231   }
00232 
00233   char recv_buffer[LineMax];
00234   if (debug_level < 2) {
00235     con->send(send_buffer, len);
00236     con->setBaudrate(write_baudrate); //connect(write_baudrate);
00237     if ((con->recv(recv_buffer, 1, Timeout) <= 0) || (recv_buffer[0] != '0')) {
00238       error_message = "no reply! (expected '0')";
00239       return false;
00240     }
00241   }
00242 
00243   // 書き込みたいデータの転送
00244   int retry_times = 0;
00245   int sended = 0;
00246   do {
00247     retry_times = 0;
00248 
00249     int srec_size = 0;
00250     bool doSend = fillSendBuffer(&srec_size,
00251                                  send_buffer, &code[sended], size - sended);
00252     if (srec_size <= 0) {
00253       error_message = "S-Format file error!";
00254       return false;
00255     }
00256     if (doSend && (debug_level > 0)) {
00257       for (int i = 0; i < 4 + 32 + 1; ++i) {
00258         fprintf(stderr, "%02x", (unsigned char)send_buffer[i]);
00259       }
00260       fprintf(stderr, "\n");
00261     }
00262     sended += srec_size;
00263     if (view_callback) {
00264       view_callback(sended, size);
00265     }
00266     if (debug_level >= 2) {
00267       continue;
00268     }
00269 
00270     do {
00271       if (doSend) {
00272         con->send(send_buffer, 4 + 32 + 1);
00273       }
00274       int n = con->recv(recv_buffer, 1, Timeout);
00275       if (!doSend || ((n > 0) && (recv_buffer[0] == '0'))) {
00276         break;
00277       }
00278       if (n < 1) {
00279         error_message = "reply timeout!";
00280         return false;
00281 
00282       } else if (recv_buffer[0] == 'E') {
00283         error_message = "flush writing fail!";
00284         return false;
00285       }
00286 
00287     } while (retry_times++ < RetryMax);
00288     if (retry_times == RetryMax) {
00289       error_message = "retry times over";
00290       return false;
00291     }
00292   } while (sended < size);
00293 
00294   mode = Writed;
00295   return true;
00296 }
00297 

Generated on Mon Apr 13 22:52:05 2009 by  doxygen 1.5.7.1