UMEHOSHI ITA TOP PAGE COMPUTER SHIEN LAB
このソースで、1byteずつ受け取ったデータが「UME専用Hexコマンド」であるか判定し、その応答処理を行っています。
これを実現する主要関数が、select_command、set_commad_charです。
select_command関数は、set_commad_charで記憶した情報を元に、コマンドとして判定した場合のUSB応答処理と、USB処理ループ(My_APP_Tasks関数)に知らせる戻り値を返します。
set_commad_charで引数の1byteデータを呼び出す繰り返しで、引数文字群に対するUME専用Hexコマンドの判定を行って、
hex_cnt、hex_cmd、hex_num、・・・・・、 hex_cntなどの変数群を設定します。
select_command関数も同じbyteデータを引数に持ちますが、それが改行でUME専用Hexコマンド終端と判断した場合に、set_commad_charで記憶した変数群を
使って、UME専用Hexコマンドの応答処理を行います。
select_command関数の応答処理は、send_command_char_responseでUSBやUART1に出力されます。
(send_command_str_response関数を多用してますが、それは最終的に send_command_char_response処理を呼び出しています。)
send_command_char_response関数では
USBが接続状態で、USBに送信可能状態の場合だけUSBに出力して、UART1コマンド状態の場合だけuartSndBufのリングバッファへ送信データをセットする必要があります。
PowerON状態から、一度でもUSBから受信があったら usb_recieved_flagがtrue となる変数があり、それをUSBに送信可能状態としています。
#ifndef _MY_USB_CMD_H /* Guard against multiple inclusion */ #define _MY_USB_CMD_H void set_hex_string(uint16_t d, char s[]); char *set_decimal_string(int d, char s[], int width); int set_uint_str(uint32_t d, char s[], char c, int width); #define HEX(c) (c < 10 ? c + '0' : c - 10 + 'A') #define DEC(c) (c >= 'A' ? c - 'A' + 10: c - '0') extern int flagThrough;//スルーモードで 1 extern int flagEcho;// エコーモードで1 // --ここから: USB出力用リングバッファと関連関数---------------------------------- #define OB_SIZE 48 //16の倍数でなければならない。(out buffer size) #define OB_MAX (512+2) extern uint8_t outBuffers[OB_MAX][OB_SIZE] __attribute__((coherent, aligned(16))); extern uint32_t outDataNumb[OB_MAX]; //上記の各配列に記憶されるデータのbyte数 extern int outBuffCount;//これが「OB_MAX」に達した時点がバッファフル状態 extern int outDataCount;//outBuffersに記憶されるバイト数 extern int flagErrorSetOutData;//バッファフルでデータをsetOutDataを使うと、1がセット extern int numbOutputs;//outBuffers出力の始まりから送信終了まで、出力データ数を保持する void init_outBuffers();//上記出力用リングバッファ用変数の初期化(APP_State_Resetで利用) void send_16byte(uint32_t data); void send_char(char data); void setBreakBuffer(); void send_string(char *s);//文字列をUSBへ送信するための登録( API 関数) void send_hex_low(uint32_t d);//dの下位16ビットを16進8桁でUSBhの出力登録 void send_hex_hi(uint32_t d);//dの上位16ビットを16進8桁でUSBhの出力登録 void send_decimal(int d, int width);//dを10進でwidth幅文字列で出力登録 void send_padding_uint(uint32_t d, char c, int width);//uintの10進幅で出力登録 int get_capacity();// outBuffersの残りメモリブロック取得 bool request_acc_outbuff(uint16_t id);// outBuffers関連変数の使用権の取得 uint16_t release_acc_outbuff(uint16_t id);// outBuffers関連変数の使用権の開放 // dのdoubleをwの幅指定でprecisonの精度幅の文字列を送信。 void send_float(double d, int width, int precison); // dのdoubleをwの幅指定でprecisonの精度幅の指数表現文字列を送信。 void send_exponent(double d, int width, int precison); void send_ume_id(); int dummy_recive(uint8_t cdata);// USBからの置き換え可能な受信処理 void requset_send_usb_if_available(); uint8_t* getSendBuff();// 現在のバッファを終わらせて送信。 void noticeSendCcomplete(); // 上記送信処理が終わった通知に対する処理 // --ここまで: USB出力用リングバッファと関連関数---------------------------------- char select_command(uint8_t c);// // 逐次に受け取る引数がコマンドと判定したら実行 char set_commad_char(uint8_t c);// 逐次に受け取る引数で、コマンドを解析して記録 char set_recive_data(uint8_t cdata, int flagBreak) ;//上記2つを使った受信関数 #endif /* _MY_USB_CMD_H */
/*
* USB の送受信アプリに必要な処理
* UMEHOSHI ITA USB受信の受け口となる関数「set_recive_data」の定義
* UMEHOSHI ITA USBからの送信命令 「send_string」「send_hex_low」「send_hex_hi」
* 「send_decimal」etc
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <xc.h>
#include "my_app.h"
#include "my_usb_cmd.h"
#include "my_beep.h"
#include "my_sys.h"
#include "my_uart.h"
#include "common.h"
int flagThrough = 0; //スルーモードで 1
static char code_to_nomal_mode[80] = "\ncode from through mode to nomal mode 123\r";
static int code_to_size = 0; //上記の文字サイズを記憶
static int code_to_nomal_idx = 0; // 上記の記憶、チェック用
int flagEcho = 1; // エコーモードで1
// "\nE\r" or "\rE\r" or "\rE\n" or "\nE\n" の受付で、1と0が交互に切り替わる。
char message[128]; // メッセージ用文字列の一時記憶用
void (*go_func)(void); // USBからの実行指示で実行する関数スタートアドレス記憶変数
int safetyflag= 1;// 書き込み範囲を制限 追加[2023-4]
//dのデータ下位16ビットを16進4桁文字列にして、[5]の記憶域のsにセットする。
void set_hex_string(uint16_t d, char s[]) {
int i;
for (i = 3; i >= 0; i--) {
char c = (char) (d & 0x0f);
c = c >= 10 ? c - 10 + 'A' : c + '0';
s[i] = c;
d >>= 4;
}
s[4] = '\x0';
}
//dのintデータが符号付きの前提で、10進数文字列にして、[12]の記憶域のsにセットする。
// 幅指定は最大が11文字で、少ない場合は拡張され、戻り値で調整される。
//(戻り値はwidthを利用した、sからずれた値になり、戻り値を表示することで幅指定を実現)
char *set_decimal_string(int d, char s[], int width) {
s[0] = ' ';
int x10 = 1000000000;
int minus = d < 0;
int sign_pos = -1;
if (minus == 1) d = -d; //正に設定
int i = 1;
for (; i <= 10; i++) {
int x = d / x10;
if (x != 0 && sign_pos == -1) sign_pos = i - 1;
if (sign_pos == -1) {
s[i] = ' ';
} else {
s[i] = x + '0';
}
d -= x * x10;
x10 /= 10;
}
char *p = s + (11 - width);
if (sign_pos != -1) {
s[sign_pos] = '+';
if (minus == 1) s[sign_pos] = '-';
if (11 - sign_pos > width) {
p = s + sign_pos;
}
} else {
s[10] = '0';
}
return p;
}
// dの符号なしデータの10進文字列を[12]の記憶域のaにセットする。
// 幅指定は最大が11文字で、満たない部分はcで埋める。
// 幅が足りない指定の場合は、これに収まる下位の桁だけの文字列になる。
// 幅に収まる変換が正しくできた場合は、1を返す。
int set_uint_str(unsigned d, char s[], char c, int width) {
char a[12];
int i = 0;
while (i < width) {
if (d == 0 && i > 0) a[i++] = c;
else a[i++] = d % 10 + '0';
d /= 10;
}
int j = 0;
for (j = 0; j < width; j++) {
s[j] = a[--i];
}
s[j] = 0;
if (d != 0) return 0;
return 1;
}
// USB出力用リングバッファ関連変数と関連関数 ======================================
uint32_t outDataNumb[OB_MAX]; // 下記の各配列に記憶されるデータのbyte数
uint8_t outBuffers[OB_MAX][OB_SIZE] __attribute__((coherent, aligned(16)));
int idxSetOutBuf; //バッファからの取り出し先添え字
int idxGetOutBuf; //バッファへの入力先添え字(上と違う時、出力すべきデータがある)
int outBuffCount; //これが「OB_MAX」に達した時点がバッファフル状態
int outDataCount = 0; //outBuffers全体に記憶されるバイト数
int idxSetCount; //outBuffers[idxGetOutBuf][idxSetCount]が現在の記憶域となる。
int flagErrorSetOutData; //バッファフルでデータをsetOutDataを使うと、1がセット
int numbOutputs = 0; //outBuffers出力の始まりから送信終了まで、出力データ数を保持する
//getSendBuff関数で記憶され、noticeSendCcomplete関数で0になり、フラグ的な役割もある
//上記outBuffers関連変数の排他制御管理変数
volatile uint16_t accessing_outbuffer __attribute__((section("sfrs")));
// 上記outBuffers関連変数の排他制御で、アクセス権を要求する
// id は指定は、ID_ACCESS_XXXXXXの定義で決めて使う。
// 割り込み時にoutBuffersを操作する使う排他制御用の権限要求関数
bool request_acc_outbuff(uint16_t id) {
if (accessing_outbuffer == id) {
return true;
}
if (accessing_outbuffer != 0) {
return false;
}
accessing_outbuffer |= id;
if (accessing_outbuffer == id) {
return true; // outBuffersへのアクセス権を得た
}
accessing_outbuffer &= ~id;
return false;
}
// 上記割込み取得した権限を返す関数
uint16_t release_acc_outbuff(uint16_t id) {
return accessing_outbuffer &= ~id; //出力バッフ利用終了
}
// USBへの送信データがoutBuffersのバッファにあるならUSB送信を促す
void requset_send_usb_if_available() {
static int pre_outDataCount = 0;
if (outBuffCount == 0 //出力すべき回数がゼロ
&& outDataCount > 0 //USBへの出力登録byte数がある。
&& pre_outDataCount == outDataCount) { // 出力登録byte数に変動がない
setBreakBuffer(); //USBへの出力すべき回数をアップ(出力を促す)
}
pre_outDataCount = outDataCount; //USBへの出力登録byte数
}
//上記outBuffersの残り容量([OB_SIZE]のブロック数)
// おおよその残りバイト数は、[この関数の戻り値]×OB_SIZEで算出できる。
int get_capacity() {
return (OB_MAX - outBuffCount);
//return outBuffCount;
}
// 上記 USB出力用リングバッファ関連変数 の初期化(APP_State_Resetで呼び出す)
void init_outBuffers() {
idxSetOutBuf = 0; //バッファからの取り出し先添え字
idxGetOutBuf = 0; //バッファへの入力先添え字(上と違う時、出力すべきデータがある)
outBuffCount = 0; //これが「OB_MAX」に達した時点がバッファフル状態
outDataCount = 0; //outBuffers全体に記憶されるバイト数
idxSetCount = 0; //outBuffers[idxGetOutBuf][idxSetCount]が現在の記憶域となる。
// ( outDataNumb[]の配列に記憶直後にidxSetCountを0にする。)
flagErrorSetOutData = 0;//バッファフルでsetOutDataを使うと1がセットがそのクリア
// ( :202503 上記追加)
numbOutputs = 0; //outBuffers出力の始まりから送信終了まで、出力データ数を保持する
accessing_outbuffer = 0; //上記変数がMy_APP_Tasks内でアクセス中の時true
}
// USBへの出力データを行う時にエラーチェックするサブ関数
static bool check_on_error() {
static bool errorFlag = false;
if (errorFlag) return false;
if (outBuffCount + 1 >= OB_MAX - 2) {// -2の余裕
flagErrorSetOutData = 1;
if (errorFlag == 0) {// バッファブロックの最後にエラー文字列をセット
if (outDataNumb[idxSetOutBuf] != 0) {// ブロックにデータがある?
if (++idxSetOutBuf >= OB_MAX) idxSetOutBuf = 0; //次のブロックへ
idxSetCount = 0;
outBuffCount++;
}
outBuffers[idxSetOutBuf][idxSetCount++] = '\r'; //"\r\nB ERR\r\n"
outBuffers[idxSetOutBuf][idxSetCount++] = '\n';
outBuffers[idxSetOutBuf][idxSetCount++] = 'B';
outBuffers[idxSetOutBuf][idxSetCount++] = ' ';
outBuffers[idxSetOutBuf][idxSetCount++] = 'E';
outBuffers[idxSetOutBuf][idxSetCount++] = 'R';
outBuffers[idxSetOutBuf][idxSetCount++] = 'R';
outBuffers[idxSetOutBuf][idxSetCount++] = '\r';
outBuffers[idxSetOutBuf][idxSetCount++] = '\n';
outDataNumb[idxSetOutBuf] = idxSetCount; // 1バッファ内のデータサイズ
outDataCount += idxSetCount; // 全バッファ内のデータサイズ
if (++idxSetOutBuf >= OB_MAX) idxSetOutBuf = 0; //次のブロックへ
idxSetCount = 0;
outBuffCount++;
}
errorFlag = true;
return false;
}
return true;
}
// 引数の1byteを上記のUSB出力用バッファ入れる。
// outBuffers[idxSetOutBuf]バッファ内の位置や数などの情報も更新される
// リングバッファのリング更新(idxSetOutBufの変更)はしない。
static uint8_t setOutData(uint8_t data) {//dataをバッファにセット
if (appData.isConfigured == false) return 0;
if (!check_on_error()) return 0;
outBuffers[idxSetOutBuf][idxSetCount++] = data;
outDataNumb[idxSetOutBuf] = idxSetCount; // 1バッファ内のデータサイズ
outDataCount++; // 全バッファ内のデータサイズ
return data; //check sum 計算用に使う戻れ値
}
// sizeの個数数のデータをUSB出力用バッファ(outBuffers)に入れる。
// 出力バッファへのセットは、setOutDataを使う。
// outBuffers[idxSetOutBuf]が一杯になれば、idxSetOutBuf変更でリングバッファを更新
static uint16_t setOutDatas(uint8_t *datas, int size) {
if (appData.isConfigured == false) return 0;
int n = 0;
uint16_t sum = 0;
while (n < size) {
if (flagErrorSetOutData == 1) break;
if (idxSetCount >= OB_SIZE) {
if (++idxSetOutBuf >= OB_MAX) {// 次のバッファに進む
idxSetOutBuf = 0; // リングバッファの先頭に戻る。
}
idxSetCount = 0;
outBuffCount++; // バッファ使用数が増える
}
setOutData(datas[n]); //1byteをバッファにセット
sum += datas[n++];
}
return sum;
}
//文字列をUSB出力用バッファ入れる。
// setOutDatasを使う。(必要に応じて自動的にリングバッファを更新)
static uint16_t setOutString(uint8_t *s) {
int size = 0;
while (s[size])size++;
return setOutDatas(s, size);
}
// 現在使っているバッファを終わらせて、次のバッファを使うように進める。
// リングバッファを強制的更新(idxSetOutBufを変更する。)
void setBreakBuffer() {
if (appData.isConfigured == false) return;
if (!check_on_error()) return;
//if(outDataNumb[idxGetOutBuf] == 0) return;//現在のバッファが空ならリターン
if (outDataNumb[idxSetOutBuf] == 0) return; //現在のバッファが空ならリターン
if (++idxSetOutBuf >= OB_MAX) {// 次のバッファに進む
idxSetOutBuf = 0; // リングバッファの先頭に戻る。
}
idxSetCount = 0;
outBuffCount++; // バッファ使用中の数が増える
}
// dataの1byteをUSB出力用バッファ(outBuffers)に入れる。(バイナリにも可能)
void send_char(char data) {
if (appData.isConfigured == false) return;
if (flagErrorSetOutData == 1) return;
if (idxSetCount >= OB_SIZE) {
if (++idxSetOutBuf >= OB_MAX) {// 次のバッファに進む
idxSetOutBuf = 0; // リングバッファの先頭に戻る。
}
idxSetCount = 0;
outBuffCount++; // バッファ使用数が増える
}
setOutData(data); //1byteをバッファにセット
}
// 2バイト、リトルエンディアンでUSB送信
void send_16byte(uint32_t data) {
send_char(data & 0x0ff);
send_char((data >> 8) & 0x0ff);
setBreakBuffer();
}
// sの文字列を、USBの出力バッファに登録する。(USBの初期化が済んでいない場合は無視)
// (割り込みルーチンから呼ぶ場合は、注意が必要!)
void send_string(char *s) {
if (appData.isConfigured) {//USBが接続されて、初期化済みか?
setOutString(s);
setBreakBuffer();
}
}
// dのデータ下位16ビットを16進4桁でUSBの出力バッファに登録する。
void send_hex_low(uint32_t d) {
char s[5];
set_hex_string(d, s);
send_string(s);
}
// dのデータ上記16ビットを16進4桁でUSBの出力バッファに登録する。
void send_hex_hi(uint32_t d) {
send_hex_low(d >> 16);
}
// dのintデータを10進10桁でUSBの出力バッファに登録する。
// 幅指定は最大が11文字で、少ない場合は拡張される。欠けずに表示する
void send_decimal(int d, int width) {
char s[12] = "-2147483648"; // 0x8fffffff
if (d == 0x80000000) {
send_string(s);
return;
}
char *p=set_decimal_string(d, s, width);
send_string(p);
}
// dの符号なしを幅指定の10文字列で送信する。幅に満たない空間はcで埋める
void send_padding_uint(uint32_t d, char c, int width) {
char s[12];
set_uint_str(d, s, c, width); // 0で埋めた10進文字列に
send_string(s);
}
// dのdoubleをwの幅指定でprecisonの精度幅の文字列を送信。
void send_float(double d, int width, int precison) {
char fmt[8];
char s[32];
sprintf(fmt, "%%%d.%df", width, precison);
sprintf(s, fmt, d);
send_string(s);
}
// dのdoubleをwの幅指定でprecisonの精度幅の指数表現文字列を送信。
void send_exponent(double d, int width, int precison) {
char fmt[8];
char s[32];
sprintf(fmt, "%%%d.%de", width, precison);
sprintf(s, fmt, d);
send_string(s);
}
void send_ume_id(){
//send_string("ume202107");
//send_string("ume202304");// 変更[2023-4]
send_string(_UME_ID);// 変更[2025-4]
}
// USB CDC の送信する時に、現在の対象となるバッファが必要で、その取得関数。
// (my_app.c のMy_APP_Tasks ( )の中で使う))
// グローバル変数のnumbOutputsに、送信データ数をセット(フラグ的な役割もある)
uint8_t* getSendBuff() {//
numbOutputs = outDataNumb[idxGetOutBuf]; // returnバッファ内のデータbyte数
outDataNumb[idxGetOutBuf] = 0; //バッファ内データ数クリア
return &outBuffers[idxGetOutBuf][0];
}
// 上記のgetSendBuffで得られたバッファの送信処理終了時点で、通知に対する処理
// (my_app.c のMy_APP_Tasks ( )の中で使う)
// グローバル変数のnumbOutputsの送信データ数0に戻すを。(フラグ的な役割もある)
void noticeSendCcomplete() {
if (numbOutputs == 0) return; //出力中でないならなにもしない。
if (++idxGetOutBuf >= OB_MAX) {
idxGetOutBuf = 0; //リングバッファなので先頭に戻る。
}
outBuffCount--; // バッファ内の送出が終わったので、使用中バッファの数を減らす
outDataCount -= numbOutputs; // 送信データ数で、バッファ内のデータ数を減らす
numbOutputs = 0;
}
// USB出力用リングバッファと関連関数 ===========ここまで==========================
// USB 受信コマンド関連の変数定義 ここから ======================================
uint8_t recieveSetBuffer[256]; //Sコマンドで受信したデータの格納用
int idxRecieveSet = 0;
//----------------------------------------------
uint8_t hex_cmd; //受信コマンド文字 [G S R E T]
uint8_t hex_num; //受信データ部のサイズ
uint8_t hex_num_count = 0; // 上記 hex_num の数まで受信を数える制御用
uint32_t hex_adr; //受信データ部のアドレス
uint8_t hex_typ; //受信データ種別
uint8_t hex_dat; //受信データ
uint8_t hex_chk; //受信したチェックサム
uint8_t hex_chk_calc; //上記チェックサムと比較するために受信データを加算する変数
// 以下の制御用変数は、対応する処理に移行する直前で0に戻す
uint32_t hex_cnt = 0; //制御用で、受信データ数を数える。(SWITGHで分岐)
uint32_t hex_low = 0; ////制御用で、16進で下位バイトの時に1
uint8_t flag_to_check_sum = 0; // 1になったらチェックサムを計算
uint8_t flag_hex_cmd_complete = 0; //1になった時がコマンド受信の終了
// USB 受信コマンド関連の変数定義 ======================================ここまで
// USB 受信コマンド関連の関数定義 ここから ======================================
// 「UME専用Hexコマンド」を受け取った時の応答文字列を返信する場合に使う関数です。
void send_command_char_response(uint8_t cdata) {
extern bool usb_recieved_flag;// trueでUSBに送信可能状態 :202503追加
if(usb_recieved_flag){//一度でもUSBから受信があった?
send_char(cdata);
}
//send_char(cdata); // :202503 コメントにして、代わり上記に変更
if (_HANDLES[_IDX_DEF_POLLS_UART] == uart_cmd_mode_polling) {
set_data_snd_uart(cdata); // uartSndBufへの送信データをセット
}
}
void send_command_str_response(uint8_t *str) {
int i = 0;
while (str[i] != 0) {
send_command_char_response(str[i++]);
}
}
// data を 16進文字列に変換して得られるcolumnSiz個の文字並びを出力
// send_command_char_response関数を利用
// (設定したデータの合計を返す。これはチェックサムの計算に使われる。)
static uint16_t send_uint_hex(uint32_t data, int columnSize) {
uint16_t sum = 0;
uint8_t d1;
uint32_t mask = 0x0f << ((columnSize - 1) * 4);
while (columnSize > 0) {
d1 = (data & mask) >> ((columnSize - 1) * 4);
d1 = HEX(d1);
sum += d1;
send_command_char_response(d1);
columnSize--;
mask >>= 4;
}
return sum;
}
// 「G」のデータ取得コマンドに対するレスポンス
// 外部変数、hex_adr のアドレスより、hex_numのサイズ要求に対するレスポンス出力で、
// チェックサムを含めた文字列を、send_command_char_response関数、
// send_uint_hex関数で送出する。
void G_response2() {
uint16_t sum = 0;
sum += ':';
send_command_char_response(':');
sum += send_uint_hex(hex_num, 2); //データ数
sum += send_uint_hex((uint32_t) hex_adr, 8); //アドレス
sum += send_uint_hex(0, 2); //種別コード
uint8_t *p = (uint8_t *) hex_adr, *pEnd = (uint8_t *) hex_adr + hex_num;
while (p < pEnd) {
sum += send_uint_hex(*p++, 2); // 1byte設定
}
sum = 0x100 - (0x0FF & sum);
send_uint_hex(sum, 2); ///チェックサムの埋め込み
send_command_char_response(0x0D); // 13のCRを埋め込み
send_command_char_response(0x0A); // 10のLFを埋め込み(以上で改行の埋め込み)
setBreakBuffer();
}
// 「S」のデータ取得コマンドに対するレスポンス
// recieveSetBufferの内容を、hex_adrのポインタが指す記憶域に設定する。
// (hex_numの個数だけ取り出してメモリに並べる)
int setToMemory() { // EEPRO領域の書き込みを可能にする変更[2023-4] 以下変更
uint8_t n;
if ( hex_adr >= 0x9D020000 && hex_adr <= 0x9D03FFFC || safetyflag==0) {
if(hex_num % 4 != 0) {
sprintf(message, "SET:%08X %d writes do not match\r\n", hex_adr, hex_num);
return 1; // 書き込みが1ワードでない
}
uint32_t *adr = (uint32_t *)hex_adr;
int rtv = 0;
for (n = 0; n < hex_num; adr++) {
uint32_t data=recieveSetBuffer[n++];
data+=recieveSetBuffer[n++]<<8;
data+=recieveSetBuffer[n++]<<16;
data+=recieveSetBuffer[n++]<<24;
uint32_t *ptw = (uint32_t *)((uint32_t)adr+0x20000000);
rtv += _nvm_write_word((uint32_t)ptw,data);
if(rtv != 0){
sprintf(message, "SET:%08X Failed to write %02X.\r\n", hex_adr, data);
return 1; // 書き込み失敗
}
if(*adr != data){
sprintf(message, "SET:%08X %08X != %08X.\r\n", hex_adr, *adr, data);
return 1;
}
}
return 0;
} else if(hex_adr >= 0x80000000 && hex_adr <= 0x8000ffff ||
hex_adr >= 0xa0000000 && hex_adr <= 0xa000ffff || safetyflag==0){
uint8_t *p = (uint8_t *) hex_adr;
for (n = 0; n < hex_num; n++) {// RAM範囲のメモリ設定
*p++ = recieveSetBuffer[n];
}
return 0;
}
return 1;
}// EEPRO領域の書き込みを可能にする変更[2023-4] 以上変更
// 逐次に受け取る引数で、コマンドを解析データをグローバル変数へ記録
char set_commad_char(uint8_t cdata) {
static uint8_t pre_cdata='\n';// 202503:追加
hex_cnt++;
switch (hex_cnt) {
case 1://コマンド文字 種別 S R G E T
hex_cmd = cdata;
idxRecieveSet = 0;
// 20250314 コマンド(S R G T E)以外であれば、無視する次のifを追加
if(cdata!='S' && cdata!='R' && cdata!='G' &&
cdata!='E' && cdata!='T' && pre_cdata!='\n' ){
flag_to_check_sum = hex_chk_calc = hex_cnt = 0;
pre_cdata = cdata;
return 'R';
}
break;
case 2://データ数取得スタート(16進文字のデータ)
hex_num_count = hex_low = 0;
hex_num = DEC(cdata);
break;
case 3://データ数取得セット(16進文字のデータ)
hex_num <<= 4;
hex_num += DEC(cdata);
break;
case 4://アドレス取得セット(16進文字のデータ)スタート
hex_adr = DEC(cdata);
break;
case 5://アドレス数取得セット(16進文字のデータ)
case 6: case 7: case 8:
case 9: case 10: case 11:
hex_adr <<= 4;
hex_adr += DEC(cdata);
break;
case 12://レコード種別セット(16進文字のデータ)スタート
hex_typ = DEC(cdata);
break;
case 13://レコード種別取得セット(16進文字のデータ)
hex_typ <<= 4;
hex_typ += DEC(cdata);
break;
default:
if (hex_cmd == 'G' || hex_cmd == 'R') {// メモリ内容の要求コマンド
flag_to_check_sum = 1; // cdataはチェックサム→検証へ
} else if (hex_cmd == 'S') {
if (hex_num_count < hex_num) {//セットデータ
if (hex_low == 0) {
hex_low = 1;
hex_dat = DEC(cdata);
} else if (hex_low == 1) {
hex_low = 0;
hex_num_count++;
hex_dat <<= 4;
hex_dat += DEC(cdata);
recieveSetBuffer[idxRecieveSet++] = hex_dat;
}
} else if (hex_num_count == hex_num) {//データ取得終了
flag_to_check_sum = 1; // cdataはチェックサム→検証へ
}
}
}
pre_cdata = cdata;// 202503:追加
// 受信用の記憶処理のブロック終わりでチェックサムの検証 1byte(16進2文字分)
if (flag_to_check_sum == 1) {
if (hex_low == 0) {//チェックサム受信
hex_chk = DEC(cdata);
hex_low = 1;
return 'R';
} else if (hex_low == 1) {
hex_chk <<= 4;
hex_chk += DEC(cdata);
hex_low = 0;
flag_to_check_sum = 0;
if (((hex_chk_calc + hex_chk) & 0x0ff) != 0) {
sprintf(message, "check sum error %c\r\n", cdata);
send_command_str_response(message);
return 'W'; //チェックサムのエラー
}
flag_hex_cmd_complete = 1; //受信処理の完結
return 'R'; // 送信バッファになにも設定していないことを知らせる。
}
}
hex_chk_calc += cdata; //チェックサム計算
return 'R'; // 送信バッファになにも設定していないことを知らせる。
}
// 引数のデータの逐次に受け取り、コマンドと判定した時、そのコマンドを実行します。
// select_command関数は、set_commad_charで記憶した情報を元に、
// コマンドとして判定した場合のUSB応答処理と、
// USB処理ループ(My_APP_Tasks関数)に 知らせる戻り値を返します。
// 戻り値は、'W'、または'R'、または0を返します。
char select_command(uint8_t cdata) {
static uint8_t prev_cdata = 0;
// :202503 スルーモードで使われていので、コメントにして削除
//if (flagThrough == 1) { //スルーモードではUART1とスルーで通信するモード
// send_uart1(cdata); //UART1の送信用リングバッファに記憶
// return 'R';
//}
if (flagEcho && !usb_receiver_disable_flag) {
// エコーモード状態の時、USB受信データを、出力バッファに入れる。
send_command_char_response(cdata);
}
if (prev_cdata == 0x0D && cdata == 0x0A) {
prev_cdata = cdata;
if (hex_cnt == 2 && hex_cmd == 'E') {// エコーモード切り替え
flag_to_check_sum = hex_chk_calc = hex_cnt = 0;
flagEcho = !flagEcho; // エコーモード切り替え
if (flagEcho) send_command_str_response("ECHO ON\r\n");
else send_command_str_response("ECHO OFF\r\n");
return 'W';
}
if (hex_cnt == 2 && hex_cmd == 'T') {// スルーモードへ
flag_to_check_sum = hex_chk_calc = hex_cnt = 0;
send_command_str_response("Through Mode\r\n");
flagThrough = 1;
flagErrorSetOutData = 0;
init_outBuffers();
return 'W'; // 送信バッファにセットしたことを知らせる
}
flag_to_check_sum = hex_chk_calc = hex_cnt = 0;
if (flag_hex_cmd_complete) {//命令確定後の受信コマンドによる分岐
flag_hex_cmd_complete = 0;
if (hex_cmd == 'G') {// メモリ内容の取得
G_response2();
return 'W'; // 送信バッファにセットしたことを知らせる
} else if (hex_cmd == 'S') {// メモリ設定
int r = setToMemory(); // 変更[2023-4] ここから
if(r==0) {
sprintf(message, "SET:%08X\r\n", hex_adr);//成功
send_command_str_response(message);
}// 変更[2023-4] ここまで
return 'W'; // 送信バッファにセットしたことを知らせる
} else if (hex_cmd == 'R') { // 実行処理の登録
go_func = (void (*)())hex_adr;
if (!usb_receiver_disable_flag) {
sprintf(message, "START:%08X\r\n", hex_adr);
send_command_str_response(message);
return 'W'; // 送信バッファにセットしたことを知らせる
} else {
return 'R';
}
}
}
if (hex_cnt != 0) {// これが成立することはチェックサムのエラー!!
sprintf(message, "exception hex_cnt: %d\r\n", hex_cnt);
send_command_str_response(message);
return 'W';
}
return 'R'; //無視(記憶しない)
}
prev_cdata = cdata;
return 0;
}
// USB受信の置き換え可能なダミー関数
int dummy_recive(uint8_t cdata) {
return 0;
}
// USBからの1byte受信で実行する。( コマンド解析して応答処理を実行 )
char set_recive_data(uint8_t cdata, int flagBreak) {
int change = _RECIVE_USB_FUNC(cdata);
if (change == 1) return 'R';
if (flagThrough == 1) { //スルーモードではUART1とスルーで通信するモード
send_uart1(cdata); //UART1の送信用リングバッファに記憶
if (code_to_size == 0) {
code_to_size = strlen(code_to_nomal_mode);
code_to_nomal_idx = 0;
}
if (cdata == code_to_nomal_mode[code_to_nomal_idx]) {
code_to_nomal_idx++;
if (code_to_nomal_idx == code_to_size) {
flagThrough = 0; // スルーモードからノーマルに遷移
code_to_nomal_idx = 0;
}
} else {
code_to_nomal_idx = 0;
}
return 'R';
}
char rtn = select_command(cdata); // 逐次に受け取る引数がコマンド判定実行
if (rtn != 0) return rtn;
return set_commad_char(cdata); // 文字をコマンド解析バッファにセット
}