Controller Class for Mbed.

Revision:
0:4f5b9889cbc4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Controller.cpp	Fri Dec 17 10:01:19 2021 +0000
@@ -0,0 +1,332 @@
+#include "Controller.h"
+
+Controller::Controller(PinName tx, PinName rx, int baudrate) : serial(tx, rx, baudrate)
+{
+    conData.ButtonState = 0;
+    conData.RJoyX = 127, conData.RJoyY = 127, conData.LJoyX = 127, conData.LJoyY = 127;
+
+    lastButtonState = 0;
+
+    comCheck = false;
+    conAvailable = false;
+    time_out_ms = -1;
+}
+
+void Controller::init(int _time_out_ms, int _int_time_ms)
+{
+    time_out_ms = _time_out_ms;
+    int_time_ms = _int_time_ms;
+    //serial.attach(this, &Controller::update, Serial::RxIrq);
+    //timer.start();
+}
+
+bool Controller::update()
+{
+    //receptionTime = timer.read();
+    static int count_ms = time_out_ms, pre_count_ms = 0; //受信時刻と前回の受信時刻
+    count_ms += int_time_ms;
+
+    char receive_data[10];
+    unsigned int loop_count = 0, checksum = 0x00;
+    comCheck = false;
+
+#if CON_TYPE == CON_ADACHI // 安達君開発のコントローラを使う場合の処理(どのコントローラを使うかはdefine.hで設定)
+    while (loop_count < 10 && serial.readable())
+    {
+        if (serial_recieve() == '\n')
+        {
+            for (int i = 0; i < 8; i++)
+                receive_data[i] = serial_recieve();
+            for (int i = 0; i < 8; i++)
+                receive_data[i] -= 0x20;
+            for (int i = 0; i < 7; i++)
+                checksum ^= receive_data[i];
+
+            if (receive_data[7] == checksum & 0xFF)
+            {
+                comCheck = true;
+
+                //pre_conData.ButtonState = conData.ButtonState;
+                lastButtonState = ((receive_data[0] & 0x3F) << 2) | ((receive_data[1] & 0x30) >> 4);
+                conData.ButtonState |= lastButtonState;
+
+                conData.RJoyX = ((receive_data[1] & 0x0F) << 4) | ((receive_data[2] & 0x3C) >> 2);
+                conData.RJoyY = ((receive_data[2] & 0x03) << 6) | (receive_data[3] & 0x3F);
+                conData.LJoyX = ((receive_data[4] & 0x3F) << 2) | ((receive_data[5] & 0x30) >> 4);
+                conData.LJoyY = ((receive_data[5] & 0x0F) << 4) | (receive_data[6] & 0x0F);
+
+                break;
+            }
+            
+            pre_count_ms = count_ms; //受信時間の更新
+        }
+        loop_count++;
+    }
+#elif CON_TYPE == CON_ELECOM // ELECOMのコントローラを使う場合の処理(どのコントローラを使うかはdefine.hで設定)
+    // コントローラデータを取得する部分
+    static int recv_num = 0;
+    char c;
+    while (serial.readable())
+    {
+        c = serial.getc();
+        if (c == '\n')
+        {
+            if (recv_num == 10)
+            { // チェックサムは無く,9個受信したら値を格納
+                for (int i = 0; i < 9; i++)
+                    checksum += (unsigned int)(receive_data[i] - 0x20); // チェックサムの計算
+                if ((checksum & 0x3F) == (receive_data[9] - 0x20))
+                { // チェックサムの計算が合っていた場合のみ値を格納
+                    comCheck = true;
+
+                    //conData.ButtonState = 0;
+                    conData.LJoyX = 0, conData.LJoyY = 0, conData.RJoyX = 0, conData.RJoyY = 0;
+                    lastButtonState = (unsigned int)(receive_data[0] - 0x20);
+                    lastButtonState |= (unsigned int)(receive_data[1] - 0x20) << 6;
+                    lastButtonState |= (unsigned int)(receive_data[2] - 0x20) << 12;
+
+                    conData.LJoyX |= (unsigned int)(receive_data[3] - 0x20);
+                    conData.LJoyX |= (unsigned int)((receive_data[4] - 0x20) & 0x03) << 6;
+                    conData.LJoyX = abs(conData.LJoyX - 0xFF);
+
+                    conData.LJoyY |= (unsigned int)((receive_data[4] - 0x20) & 0x3C) >> 2;
+                    conData.LJoyY |= (unsigned int)((receive_data[5] - 0x20) & 0x0F) << 4;
+                    conData.LJoyY = abs(conData.LJoyY - 0xFF);
+
+                    conData.RJoyX |= (unsigned int)((receive_data[5] - 0x20) & 0x30) >> 4;
+                    conData.RJoyX |= (unsigned int)((receive_data[6] - 0x20) & 0x3F) << 2;
+                    conData.RJoyX = abs(conData.RJoyX - 0xFF);
+
+                    conData.RJoyY |= (unsigned int)(receive_data[7] - 0x20);
+                    conData.RJoyY |= (unsigned int)((receive_data[8] - 0x20) & 0x03) << 6;
+                    conData.RJoyY = abs(conData.RJoyY - 0xFF);
+
+                    int buttonPushNum = 0;
+                    for (int i = 0; i < 16; i++)
+                    {
+                        buttonPushNum += (conData.ButtonState >> i) & 0x0001;
+                    }
+                    if (buttonPushNum > 5)
+                    {
+                        //conData.ButtonState = pre_conData.ButtonState;
+                        comCheck = false;
+                    }
+                    else
+                    {
+                        conData.ButtonState |= lastButtonState;
+                    }
+                    
+                    pre_count_ms = count_ms; //受信時間の更新
+                }
+            }
+            recv_num = 0;
+        }
+        else
+        {
+            receive_data[recv_num] = c;
+            recv_num++;
+        }
+    }
+#elif CON_TYPE == CON_DS4    // DualShock4を使う場合の処理(どのコントローラを使うかはdefine.hで設定)
+    // コントローラデータを取得する部分
+    static int recv_num = 0;
+    char c;
+    while (serial.readable())
+    {
+        c = serial.getc();
+        //Serial.print(c);
+        if (c == '\n')
+        {
+            if (recv_num == 10)
+            { // データ数はチェックサム含めて10個(0~9)
+                checksum = 0;
+                for (int i = 0; i < 9; i++)
+                    checksum ^= (unsigned int)(receive_data[i] - 0x20); // チェックサムの計算
+                if ((checksum & 0x3F) == (receive_data[9] - 0x20))
+                { // チェックサムの計算が合っていた場合のみ値を格納
+                    comCheck = true;
+
+                    //conData.ButtonState = 0;
+                    conData.LJoyX = 0, conData.LJoyY = 0, conData.RJoyX = 0, conData.RJoyY = 0;
+                    lastButtonState = (unsigned int)(receive_data[0] - 0x20) & 0x3F;
+                    lastButtonState |= (unsigned int)((receive_data[1] - 0x20) & 0x3F) << 6;
+                    lastButtonState |= (unsigned int)((receive_data[2] - 0x20) & 0x0F) << 12;
+
+                    conData.LJoyX |= (unsigned int)(receive_data[3] - 0x20);
+                    conData.LJoyX |= (unsigned int)((receive_data[4] - 0x20) & 0x03) << 6;
+                    conData.LJoyX = abs(conData.LJoyX - 0xFF);
+
+                    conData.LJoyY |= (unsigned int)((receive_data[4] - 0x20) & 0x3C) >> 2;
+                    conData.LJoyY |= (unsigned int)((receive_data[5] - 0x20) & 0x0F) << 4;
+                    conData.LJoyY = abs(conData.LJoyY - 0xFF);
+
+                    conData.RJoyX |= (unsigned int)((receive_data[5] - 0x20) & 0x30) >> 4;
+                    conData.RJoyX |= (unsigned int)((receive_data[6] - 0x20) & 0x3F) << 2;
+                    conData.RJoyX = abs(conData.RJoyX - 0xFF);
+
+                    conData.RJoyY |= (unsigned int)(receive_data[7] - 0x20);
+                    conData.RJoyY |= (unsigned int)((receive_data[8] - 0x20) & 0x03) << 6;
+                    conData.RJoyY = abs(conData.RJoyY - 0xFF);
+
+                    // 通信ミスであり得ない数のボタン数押されていた場合に無視する処理
+                    int buttonPushNum = 0;
+                    for (int i = 0; i < 16; i++)
+                    {
+                        buttonPushNum += (lastButtonState >> i) & 0x0001;
+                    }
+                    if (buttonPushNum > 5)
+                    {
+                        //conData.ButtonState = pre_conData.ButtonState;
+                        comCheck = false;
+                    }
+                    else
+                    {
+                        conData.ButtonState = lastButtonState & 0xFFFF;
+                    }
+
+                    pre_count_ms = count_ms; //受信時間の更新
+                }
+            }
+            recv_num = 0;
+        }
+        else
+        {
+            receive_data[recv_num] = c;
+            recv_num++;
+        }
+    }
+
+#endif
+
+    if(!(time_out_ms == -1)) conAvailable = (time_out_ms > (count_ms - pre_count_ms)); //タイムアウトとインターバルの比較
+    else conAvailable = true;
+    if(count_ms > time_out_ms * 1000) count_ms = time_out_ms; //オーバーフロー対策
+
+    return comCheck;
+}
+
+bool Controller::getComCheck(void)
+{
+    return comCheck;
+}
+
+bool Controller::available(void)
+{
+    return conAvailable;
+}
+
+bool Controller::readButton_bin(unsigned int ButtonNum)
+{ //放しているときは0,押しているときは1
+    return ((conData.ButtonState & (0x0001 << (ButtonNum - 1))) == (0x0001 << (ButtonNum - 1))) ? true : false;
+}
+
+int Controller::readButton(unsigned int ButtonNum)
+{ //放しているときは0,押しているときは1,押した瞬間は2,放した瞬間は-1
+    int result = 0;
+    if ((conData.ButtonState & (0x0001 << (ButtonNum - 1))) == (0x0001 << (ButtonNum - 1)))
+        result += 2;
+    if ((pre_conData.ButtonState & (0x0001 << (ButtonNum - 1))) == (0x0001 << (ButtonNum - 1)))
+        result -= 1;
+    return result;
+}
+
+unsigned int Controller::getButtonState()
+{
+    return conData.ButtonState;
+}
+
+void Controller::clearButtonState()
+{
+    pre_conData.ButtonState = conData.ButtonState;
+}
+
+ControllerData Controller::getConData()
+{
+    return conData;
+}
+
+double Controller::readJoyRX()
+{
+    if (conData.RJoyX == 127)
+        return 0;
+    return ((double)conData.RJoyX - 127.5) / 127.5;
+}
+
+double Controller::readJoyRY()
+{
+    if (conData.RJoyY == 127)
+        return 0;
+    return ((double)conData.RJoyY - 127.5) / 127.5;
+}
+
+double Controller::readJoyLX()
+{
+    if (conData.LJoyX == 127)
+        return 0;
+    return ((double)conData.LJoyX - 127.5) / 127.5;
+}
+
+double Controller::readJoyLY()
+{
+    if (conData.LJoyY == 127)
+        return 0;
+    return ((double)conData.LJoyY - 127.5) / 127.5;
+}
+
+uint8_t Controller::readJoyRXbyte()
+{
+    return conData.RJoyX;
+}
+
+uint8_t Controller::readJoyRYbyte()
+{
+    return conData.RJoyY;
+}
+
+uint8_t Controller::readJoyLXbyte()
+{
+    return conData.LJoyX;
+}
+
+uint8_t Controller::readJoyLYbyte()
+{
+    return conData.LJoyY;
+}
+
+unsigned int Controller::getButtonFlagRise()
+{
+    // 立ち上がり,立下りのフラッギング処理 (フラグクリアは別関数で)
+    unsigned int buttonFlagRise = 0;
+    if (pre_conData.ButtonState != conData.ButtonState)
+    {
+        for (int i = 0; i < 16; i++)
+        {
+            int mask = 0x01 << i;
+            if ((conData.ButtonState & mask) != (pre_conData.ButtonState & mask))
+            {
+                if ((conData.ButtonState & mask) == mask)
+                    buttonFlagRise |= (conData.ButtonState & mask);
+            }
+        }
+    }
+    return buttonFlagRise;
+}
+
+unsigned int Controller::getButtonFlagFall()
+{
+    unsigned int buttonFlagFall = 0;
+    if (pre_conData.ButtonState != conData.ButtonState)
+    {
+        for (int i = 0; i < 16; i++)
+        {
+            int mask = 0x01 << i;
+            if ((conData.ButtonState & mask) != (pre_conData.ButtonState & mask))
+            {
+                if ((pre_conData.ButtonState & mask) == mask)
+                    buttonFlagFall |= (pre_conData.ButtonState & mask);
+            }
+        }
+    }
+    return buttonFlagFall;
+}
+