Communication Class and Controller Class (ControllerForMbed Class)

Dependencies:   SoftPWM

Controller.cpp

Committer:
kikuchi8810
Date:
2021-12-23
Revision:
2:fd0c21600586
Parent:
0:a33375289d79

File content as of revision 2:fd0c21600586:

// DS4のみ通信が確認できているバージョンで,プロジェクトに公開しているクラス
#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 - int_time_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;
}