     // protocol
     //   segd1234[CR][LF]
     if (mode == MODE_WAITING_S) {
-      if (c == 's') mode = MODE_WAITING_E;
-      else mode = MODE_WAITING_S;
+      if (c == 's') change_mode(MODE_WAITING_E);
+      else change_mode(MODE_WAITING_S);
     }
     else if (mode == MODE_WAITING_E) {
-      if (c == 'e') mode = MODE_WAITING_G;
-      else mode = MODE_WAITING_S;
+      if (c == 'e') change_mode(MODE_WAITING_G);
+      else change_mode(MODE_WAITING_S);
     }
     else if (mode == MODE_WAITING_G) {
-      if (c == 'g') mode = MODE_WAITING_D;
-      else mode = MODE_WAITING_S;
+      if (c == 'g') change_mode(MODE_WAITING_D);
+      else change_mode(MODE_WAITING_S);
     }
     else if (mode == MODE_WAITING_D) {
-      if (c == 'd') mode = MODE_RECV_DIGIT;
-      else mode = MODE_WAITING_S;
+      if (c == 'd') change_mode(MODE_RECV_DIGIT);
+      else change_mode(MODE_WAITING_S);
     }
     else {
-      if (0x30 <= c && c <= 0x39) { // 0-9
-        buf[buf_idx] = c - 0x30;
-        if (buf_idx < 4) buf_idx ++;
-      }
-      else if (c == 0x20) { // space
-        buf[buf_idx] = 10; // blank
-        if (buf_idx < 4) buf_idx ++;
-      }
-      else if (c == 0x0d) { // CR
+      if (c == 0x0d) { // CR
         // nothing to do...
       }
       else if (c == 0x0a) { // LF
         update7seg();
-        mode = MODE_WAITING_S;
+        change_mode(MODE_WAITING_S);
+      }
+      else if (0x00 <= c && c <= 0x1f) {
+        // invalid charactor data...
+        change_mode(MODE_WAITING_S);
+      }
+      else if (c == '.' || c == ',') {
+        int idx = buf_idx - 1;
+        idx = idx < 0 ? 0 : idx;
+        dot[idx] = 1;
       }
       else {
-        mode = MODE_WAITING_S;
+        buf[buf_idx] = c;
+        if (buf_idx < 4) buf_idx ++;
       }
     }
   }
   mySseg.update();
 }
+

#define MODE_RECV_DIGIT  4
int mode = MODE_WAITING_S;

uint8_t patterns[] = {
  NUM_PAT_0,
  NUM_PAT_1,
  NUM_PAT_2,
  NUM_PAT_3,
  NUM_PAT_4,
  NUM_PAT_5,
  NUM_PAT_6,
  NUM_PAT_7,
  NUM_PAT_8,
  NUM_PAT_9,
  0b00000000  // blank
};

int buf[4];
int buf_idx = 0;

void setup()

  mySseg.begin();

  Serial.begin(9600);

  // banner
  Serial.println("hello7seg");
  show_text("HE#o", 1);
  show_text("7SEG", 1);
  show_text("    ", 0);

  // initial mode
  change_mode(MODE_WAITING_S);
}

void clear_buf() {
  buf_idx = 0;
  
  for (int i = 0; i < 4; ++i) {
    buf[i] = ' ';
    dot[i] = 0;
  }
}

void show_text(char *text, int sec) {
  if (text == NULL) return;
  
  clear_buf();

  int len = strlen(text);
  len = len < 4 ? len : 4;
  
  for (int i = 0; i < len; ++i) {
    buf[i] = text[i];
  }
  update7seg();

  for (int t = 0; t < len; ++t) {
    for (int i = 0; i < 17000; ++i) {
      mySseg.update();
    }
  }
}

void update7seg() {
  uint8_t c0, c1, c2, c3;

  c0 = ascii127[buf[0]] | (0x00000001 * dot[0]);
  c1 = ascii127[buf[1]] | (0x00000001 * dot[1]);
  c2 = ascii127[buf[2]] | (0x00000001 * dot[2]);
  c3 = ascii127[buf[3]] | (0x00000001 * dot[3]);

  mySseg.writeRawData(c0, c1, c2, c3);
  clear_buf();
}

void change_mode(int m) {
  mode = m;
  clear_buf();
}

void loop()
