#include <string.h>
 
// ピン設定 | Pin assignments
#define GT_DTR 4      // DTR
#define GT_DSR 6      // DSR
#define GT_TRDY 7     // TRDY <--未使用 | unused in this sample
 
 
void setup() {
  //  ピンの設定 | Pin setting
  pinMode(GT_DTR, INPUT);
  pinMode(GT_DSR, OUTPUT);
  pinMode(GT_TRDY, INPUT);
  digitalWrite(GT_DSR, LOW);
 
 // シリアル通信の初期化 | Serial communication initialization
  Serial.begin(38400); // 38400bps Baud rate
  Serial.setTimeout(100); // Serial timeout
 
 
 
  // メーターの最小値と最大値を設定する | Set min and max values for meter
  setMeterRange(0, 160);
}
 
void loop() {
  // センサーから値を読み取る | Read value from sensor
  int sensorValue = analogRead(A0);
 
  // センサーの値を0〜160の範囲にマッピングし、制限内に収める | Map the sensor value to the range 0-160 and constrain within limits
  int meterValue = constrain(map(sensorValue, 0, 1023, 160, 0), 0, 160);
 
 
  // メーターの値をGT-SPに送信 | Send meter value to GT-SP
  sendMeterValue(meterValue);
 
  // メーターの字背景画像を変 | Change background image of the meter
  updateMeterBackground(meterValue);
 
  // GT-SP上のテキストオブジェクト（オブジェクトNo.2）に値を表示 | Display the value in the text object (Object No.2) on GT-SP
  gtsp_ObjPrpSet_string(2, 0x40, String(meterValue));
 
  delay(100); // Wait for 100 milliseconds
}
 
// GT-SPのメーターの最小値と最大値を設定 |  Set min and max values for meter on GT-SP
void setMeterRange(int minValue, int maxValue) {
  gtsp_ObjPrpSet_val(0, 0x1E, 4, minValue); // Set minimum value
  gtsp_ObjPrpSet_val(0, 0x1F, 4, maxValue); // Set maximum value
}
 
// GT-SPに値を送信 | Send value to GT-SP
void sendMeterValue(int value) {
  gtsp_ObjPrpSet_val(0, 0x10, 4, value);
}
 
// メーターの字背景画像を変更 | Change background image of the meter
void updateMeterBackground(int value) {
  if (value <= 100) {
    Serial.println("Switching to Image0 (CNTS_SEL = 0)");
    gtsp_ObjPrpSet_val(0, 0x14, 1, 0); // CNTS_SEL = 0: Background Image0
  } else {
    Serial.println("Switching to Image1 (CNTS_SEL = 1)");
    gtsp_ObjPrpSet_val(0, 0x14, 1, 1); // CNTS_SEL = 1: Background Image1
  }
}
 
/********************** GT-SP関数 | Function for GT-SP **********************/
////////////////////////////////////////////////////
// オブジェクト制御コマンド-プロパティ読み出し（数値用）| Read property value (for Value)
////////////////////////////////////////////////////
unsigned long gtsp_ObjPrpRead_val(int obj, int prp, int ln) {
  unsigned long val;

  gt_print("CMD"); // コマンドヘッダ | Command header
  gt_put(0xd4); // オブジェクト-プロパティ設定コマンド | Object-Property Setting
  gt_put(obj >> 0); // オブジェクトNo. 下位バイト | Object No. Lower byte
  gt_put(obj >> 8); // オブジェクトNo. 上位バイト | Object No. Upper byte
  gt_put(prp >> 0); // プロパティNo. 下位バイト | Property No. Lower byte
  gt_put(prp >> 8); // プロパティNo. 上位バイト | Property No. Upper byte
  gt_put(ln >> 0); // データ長 最下位バイト | Data length Least significant byte
  gt_put(ln >> 8); // データ長 下位バイト | Data length second byte
  gt_put(ln >> 16); // データ長 上位バイト | Data length third byte
  gt_put(ln >> 24); // データ長 最上位バイト | Data length Most significant byte

  // プロパティデータ受信 | Property data received
  while (Serial.available() == 0) {}
  val = gtsp_signal_read_val();
  return val;
}

////////////////////////////////////////////////////
// データ受信（文字列用）| Receive data from GT-SP (for String)
////////////////////////////////////////////////////
String gtsp_signal_read() {
  byte res_dl[4] = "";
  unsigned long dl;
  char res_data_char[255] = "";

  if (Serial.find("RESb", 4)) {
    Serial.readBytes(res_dl, 4); // データ長抽出 | Data-length extraction
    dl = (unsigned long)(res_dl[0] + (res_dl[1] << 8) + (res_dl[2] << 16) + (res_dl[3] << 24)); // データ長変換 | Data length
    Serial.readBytes(res_data_char, dl); // データ抽出 | Read data
    Serial.print("Received data: ");
    for (unsigned int i = 0; i < dl; i++) {
      Serial.print(res_data_char[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
    return String(res_data_char); // String type conversion, return
  }
  return "";
}
 
////////////////////////////////////////////////////
// 1byte送信 | Send byte to GT-SP
////////////////////////////////////////////////////
void gt_put(unsigned char onebyte) {
  while (digitalRead(GT_DTR) == HIGH) {} // busycheck
  Serial.write(onebyte);
}

////////////////////////////////////////////////////
// 文字列送信 | Send String to GT-SP
////////////////////////////////////////////////////
void gt_print(String val) {
  int val_i;
  // 文字列を1文字ずつ送信 | Send string per one byte
  for (val_i = 0; val_i < val.length(); val_i++) {
    while (digitalRead(GT_DTR) == HIGH) {} // busycheck
    Serial.print(val.substring(val_i, val_i + 1));
  }
}
