iT邦幫忙

DAY 14
0

x86 android 設備與外部硬體溝通研究系列 第 14

x86 android 設備與外部硬體溝通研究 - Arduino firmata protocol -4 (14/30)

  • 分享至 

  • xImage
  •  

今天我們來看的主角是 firmata class 中的 processInput , 從第二天看的 digital firmata sample 我們可以知道,所有arduino收到host端的輸入資料都是由 proceddInput 處理的,讓我們一段一段的抽絲剝繭來看看他是如何運作的:

void FirmataClass::processInput(void)
{
  int inputData = FirmataSerial.read(); // this is 'int' to handle -1 when no data
  int command;
    
  // TODO make sure it handles -1 properly

  if (parsingSysex) { // 判斷是否開始解析 input command , 由 systemReset() 中我們得知這個參數預設值是 false
    if(inputData == END_SYSEX) {
      //stop sysex byte      
      parsingSysex = false;
      //fire off handler function
      processSysexMessage();
    } else {
      //normal data byte - add to buffer
      storedInputData[sysexBytesRead] = inputData;
      sysexBytesRead++;
    }
  } else if( (waitForData > 0) && (inputData < 128) ) {  //繼續接收後面的資料逐筆放到 buffer 中
    waitForData--;
    storedInputData[waitForData] = inputData;
    if( (waitForData==0) && executeMultiByteCommand ) { // got the whole message 
     // 接收由 command 送到 executeMultiByteCommand 的指令並等待收後面接續的資料長度,資料收滿 128 bit 後
      switch(executeMultiByteCommand) { //判斷輸入的 command 型態,並把後面的資料分送的對應的 callback function , 當然要順便判斷 callback function 是否已經有被註冊上來了
      case ANALOG_MESSAGE:
        if(currentAnalogCallback) {
          (*currentAnalogCallback)(multiByteChannel,
                                   (storedInputData[0] << 7)
                                   + storedInputData[1]);
        }
        break;
      case DIGITAL_MESSAGE:
        if(currentDigitalCallback) {
          (*currentDigitalCallback)(multiByteChannel,
                                    (storedInputData[0] << 7)
                                    + storedInputData[1]);
        }
        break;
      case SET_PIN_MODE:
        if(currentPinModeCallback)
          (*currentPinModeCallback)(storedInputData[1], storedInputData[0]);
        break;
      case REPORT_ANALOG:
        if(currentReportAnalogCallback)
          (*currentReportAnalogCallback)(multiByteChannel,storedInputData[0]);
        break;
      case REPORT_DIGITAL:
        if(currentReportDigitalCallback)
          (*currentReportDigitalCallback)(multiByteChannel,storedInputData[0]);
        break;
      }
      executeMultiByteCommand = 0; // 分送執行完 callback function 後,把 command 清空,讓 processInput 接收下一筆 command
    }	
  } else {
    // remove channel info from command byte if less than 0xF0
    if(inputData < 0xF0) { // 判斷 command 的範圍
      command = inputData & 0xF0;
      multiByteChannel = inputData & 0x0F;
    } else {
      command = inputData;
      // commands in the 0xF* range don't use channel data
    }
    switch (command) {
    case ANALOG_MESSAGE:// 把 command 送到 executeMultiByteCommand 這邊暫存,然後回到上一段 router 中,等待接收後面接續的資料長度          case DIGITAL_MESSAGE:
    case SET_PIN_MODE:
      waitForData = 2; // two data bytes needed
      executeMultiByteCommand = command;
      break;
    case REPORT_ANALOG: 
    case REPORT_DIGITAL:
      waitForData = 1; // two data bytes needed
      executeMultiByteCommand = command;
      break;
    case START_SYSEX: // 要直到收到這個 command 才把之後的 command 丟到上面那一大段的 router 中運作
      parsingSysex = true;
      sysexBytesRead = 0;
      break;
    case SYSTEM_RESET: // 執行 參數初始化
      systemReset();
      break;
    case REPORT_VERSION:
      Firmata.printVersion();
      break;
    }
  }
}

結論是 processInput 是一個簡單的 router 負責等待指令/資料,並呼叫對應的 callback function 來執行。

我們明天見


上一篇
x86 android 設備與外部硬體溝通研究 - Arduino firmata protocol -3 (13/30)
下一篇
x86 android 設備與外部硬體溝通研究 - Arduino firmata protocol -5 (15/30)
系列文
x86 android 設備與外部硬體溝通研究30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言