wip:reading figure
This commit is contained in:
parent
59ea084ff4
commit
aed30481ea
3 changed files with 134 additions and 5 deletions
|
@ -367,7 +367,35 @@ void USkyPortalSubsystem::CheckComplexResponse() {
|
||||||
break;
|
break;
|
||||||
case S:
|
case S:
|
||||||
CurrentStatusData = ParsePortalStatus(res);
|
CurrentStatusData = ParsePortalStatus(res);
|
||||||
|
|
||||||
//Send delegate when new informations are received
|
//Send delegate when new informations are received
|
||||||
|
if (OldStatusData != CurrentStatusData) {
|
||||||
|
|
||||||
|
for (int i = 0; i < CurrentStatusData.StatusArray.Num(); i++) {
|
||||||
|
if (CurrentStatusData.StatusArray[i] != OldStatusData.StatusArray[i]) {
|
||||||
|
if (!FalsePositive()) {
|
||||||
|
switch (CurrentStatusData.StatusArray[i])
|
||||||
|
{
|
||||||
|
case EFigureStatus::NOT_PRESENT:
|
||||||
|
break;
|
||||||
|
case EFigureStatus::PRESENT:
|
||||||
|
break;
|
||||||
|
case EFigureStatus::ADDED:
|
||||||
|
//get SkylandID
|
||||||
|
//ReadBlock;
|
||||||
|
OnSkylanderAdded.Broadcast(01, i);
|
||||||
|
case EFigureStatus::REMOVED:
|
||||||
|
OnSkylanderRemoved.Broadcast(01, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OldStatusData = CurrentStatusData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -375,6 +403,12 @@ void USkyPortalSubsystem::CheckComplexResponse() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool USkyPortalSubsystem::FalsePositive()
|
||||||
|
{
|
||||||
|
int dif = FMath::Abs(CurrentStatusData.Counter - OldStatusData.Counter);
|
||||||
|
return (dif <= 2 || dif > 254);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Verify the command response, when only a character is sended by the portal.
|
/* Verify the command response, when only a character is sended by the portal.
|
||||||
|
@ -491,7 +525,7 @@ EPortalCommand USkyPortalSubsystem::GetPortalCommandFromChar(unsigned char Char)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USkyPortalSubsystem::ReadBlock(unsigned int block, unsigned char data[0x10], int skylander) {
|
bool USkyPortalSubsystem::ReadBlock(unsigned int block, unsigned char data[0x10], int skylanderIndex) {
|
||||||
RWBlock req, res; //request and response buffers
|
RWBlock req, res; //request and response buffers
|
||||||
unsigned char followup;
|
unsigned char followup;
|
||||||
|
|
||||||
|
@ -513,7 +547,7 @@ bool USkyPortalSubsystem::ReadBlock(unsigned int block, unsigned char data[0x10]
|
||||||
|
|
||||||
memset(req.buf, 0, rw_buf_size); // Clear the request buffer (initialize all bytes to zero)
|
memset(req.buf, 0, rw_buf_size); // Clear the request buffer (initialize all bytes to zero)
|
||||||
req.buf[1] = 'Q';
|
req.buf[1] = 'Q';
|
||||||
followup = 0x10 + skylander;
|
followup = 0x10 + skylanderIndex;
|
||||||
req.buf[2] = followup;
|
req.buf[2] = followup;
|
||||||
if (block == 0) {
|
if (block == 0) {
|
||||||
req.buf[2] = followup + 0x10; // may not be needed
|
req.buf[2] = followup + 0x10; // may not be needed
|
||||||
|
@ -629,3 +663,65 @@ void FPortalStatusChecker::CheckPortalStatus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FigureDataBlock USkyPortalSubsystem::ReadFigureBlocks(uint8 FigureIndex)
|
||||||
|
{
|
||||||
|
FigureDataBlock FigureData;
|
||||||
|
FigureData.error = false; // Initialize error flag
|
||||||
|
|
||||||
|
RWBlock req, res;
|
||||||
|
|
||||||
|
// Loop over all 64 blocks
|
||||||
|
for (uint8 BlockIndex = 0; BlockIndex < FIGURE_TOTAL_BLOCKS; ++BlockIndex)
|
||||||
|
{
|
||||||
|
// Prepare the request buffer
|
||||||
|
memset(req.buf, 0, rw_buf_size);
|
||||||
|
req.buf[1] = 'Q'; // Command character
|
||||||
|
req.buf[2] = FigureIndex; // Figure index (0x00 to 0x0F)
|
||||||
|
req.buf[3] = BlockIndex; // Block index (0x00 to 0x3F)
|
||||||
|
|
||||||
|
// Send the request
|
||||||
|
Write(&req);
|
||||||
|
|
||||||
|
// Read the response
|
||||||
|
int BuffResponse = hid_read_timeout(PortalDevice, res.buf, rw_buf_size, TIMEOUT);
|
||||||
|
|
||||||
|
// Check if the response was received successfully
|
||||||
|
if (BuffResponse < rw_buf_size)
|
||||||
|
{
|
||||||
|
FigureData.error = true; // Mark error flag
|
||||||
|
UE_LOG(LogSkyportalIO, Warning, TEXT("Error receiving data for block %d of figure %d"), BlockIndex, FigureIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the response status
|
||||||
|
uint8 StatusByte = res.buf[2];
|
||||||
|
uint8 ReturnedBlockIndex = res.buf[3];
|
||||||
|
|
||||||
|
// Check for errors in the status byte
|
||||||
|
if (StatusByte == 0x01) // Error in response
|
||||||
|
{
|
||||||
|
FigureData.error = true;
|
||||||
|
UE_LOG(LogSkyportalIO, Warning, TEXT("Error reading block %d for figure %d"), BlockIndex, FigureIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (StatusByte != (0x10 + 'Q')) // Unexpected status byte
|
||||||
|
{
|
||||||
|
FigureData.error = true;
|
||||||
|
UE_LOG(LogSkyportalIO, Warning, TEXT("Unexpected status byte 0x%02X for block %d"), StatusByte, BlockIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the block index matches the requested block
|
||||||
|
if (ReturnedBlockIndex != BlockIndex)
|
||||||
|
{
|
||||||
|
FigureData.error = true;
|
||||||
|
UE_LOG(LogSkyportalIO, Warning, TEXT("Mismatched block index. Expected %d, got %d"), BlockIndex, ReturnedBlockIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy block data into FigureData
|
||||||
|
memcpy(FigureData.blockdata[BlockIndex], &res.buf[4], FIGURE_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FigureData; // Return the complete figure data
|
||||||
|
}
|
3
Source/SkyPortal/Public/SkyPortalFigure.h
Normal file
3
Source/SkyPortal/Public/SkyPortalFigure.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SkyPortalFigure.generated.h"
|
|
@ -4,6 +4,7 @@
|
||||||
#include "Subsystems/EngineSubsystem.h"
|
#include "Subsystems/EngineSubsystem.h"
|
||||||
#include "hidapi.h"
|
#include "hidapi.h"
|
||||||
#include "HAL/Runnable.h"
|
#include "HAL/Runnable.h"
|
||||||
|
#include "SkyPortalFigure.h"
|
||||||
|
|
||||||
|
|
||||||
#include "SkyPortalSubsystem.generated.h"
|
#include "SkyPortalSubsystem.generated.h"
|
||||||
|
@ -49,7 +50,7 @@ struct FPortalStatusData
|
||||||
TArray<EFigureStatus> StatusArray;
|
TArray<EFigureStatus> StatusArray;
|
||||||
|
|
||||||
// timestamp.
|
// timestamp.
|
||||||
//only one byte long. This means that after the value 0xFF, it overflows back to 0x00.
|
// only one byte long. This means that after the value 0xFF, it overflows back to 0x00.
|
||||||
// Since these are so far apart, it can be assumed that 0x00 is newer than anything in the range 0xF0 - 0xFF.
|
// Since these are so far apart, it can be assumed that 0x00 is newer than anything in the range 0xF0 - 0xFF.
|
||||||
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
|
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
|
||||||
uint8 Counter;
|
uint8 Counter;
|
||||||
|
@ -57,17 +58,40 @@ struct FPortalStatusData
|
||||||
// Should always be true
|
// Should always be true
|
||||||
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
|
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
|
||||||
bool bIsReady;
|
bool bIsReady;
|
||||||
|
|
||||||
|
// Overload the == operator
|
||||||
|
bool operator==(const FPortalStatusData& Other) const
|
||||||
|
{
|
||||||
|
if (bIsReady == Other.bIsReady && Counter == Other.Counter) {
|
||||||
|
if (StatusArray == Other.StatusArray) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overload the != operator
|
||||||
|
bool operator!=(const FPortalStatusData& Other) const
|
||||||
|
{
|
||||||
|
return !(*this == Other);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Macro constants Definitions */
|
/* Macro constants Definitions */
|
||||||
#define rw_buf_size 0x21
|
#define rw_buf_size 0x21
|
||||||
#define TIMEOUT 30000
|
#define TIMEOUT 30000
|
||||||
#define DEBUG true
|
#define DEBUG true
|
||||||
|
#define FIGURE_TOTAL_BLOCKS 64
|
||||||
|
#define FIGURE_BLOCK_SIZE 16
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char buf[rw_buf_size]; int BytesTransferred;
|
unsigned char buf[rw_buf_size]; int BytesTransferred;
|
||||||
} RWBlock;
|
} RWBlock;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char blockdata[FIGURE_TOTAL_BLOCKS][FIGURE_BLOCK_SIZE]; bool error;
|
||||||
|
} FigureDataBlock;
|
||||||
|
|
||||||
DECLARE_LOG_CATEGORY_EXTERN(LogHIDApi, Log, All);
|
DECLARE_LOG_CATEGORY_EXTERN(LogHIDApi, Log, All);
|
||||||
DECLARE_LOG_CATEGORY_EXTERN(LogSkyportalIO, Log, All);
|
DECLARE_LOG_CATEGORY_EXTERN(LogSkyportalIO, Log, All);
|
||||||
|
|
||||||
|
@ -148,6 +172,8 @@ public:
|
||||||
UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|NOT FUNCTIONING"))
|
UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|NOT FUNCTIONING"))
|
||||||
SKYPORTAL_API void SendPortalSound(USoundWave* Sound);
|
SKYPORTAL_API void SendPortalSound(USoundWave* Sound);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Change portal color, ideally should be called just at the start.For gameplay usage, use ChangePortalColorside()*/
|
/* Change portal color, ideally should be called just at the start.For gameplay usage, use ChangePortalColorside()*/
|
||||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "Color", Category = "SkyPortal|Cosmetic"))
|
UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "Color", Category = "SkyPortal|Cosmetic"))
|
||||||
SKYPORTAL_API void ChangePortalColor(const FLinearColor& Color = FLinearColor::Green);
|
SKYPORTAL_API void ChangePortalColor(const FLinearColor& Color = FLinearColor::Green);
|
||||||
|
@ -173,6 +199,9 @@ public:
|
||||||
UPROPERTY(BlueprintReadOnly)
|
UPROPERTY(BlueprintReadOnly)
|
||||||
FPortalStatusData CurrentStatusData;
|
FPortalStatusData CurrentStatusData;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
FPortalStatusData OldStatusData;
|
||||||
|
|
||||||
EPortalCommand GetPortalCommandFromChar(unsigned char Char);
|
EPortalCommand GetPortalCommandFromChar(unsigned char Char);
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,7 +214,7 @@ public:
|
||||||
bool WriteBlock(unsigned int, unsigned char[0x10], int);
|
bool WriteBlock(unsigned int, unsigned char[0x10], int);
|
||||||
bool CheckResponse(RWBlock*, char);
|
bool CheckResponse(RWBlock*, char);
|
||||||
void CheckComplexResponse();
|
void CheckComplexResponse();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,7 +236,8 @@ private:
|
||||||
// Block/byte related data write/read functions
|
// Block/byte related data write/read functions
|
||||||
bool OpenPortalHandle();
|
bool OpenPortalHandle();
|
||||||
void Write(RWBlock*);
|
void Write(RWBlock*);
|
||||||
|
FigureDataBlock ReadFigureBlocks(uint8 FigureIndex);
|
||||||
|
bool FalsePositive();
|
||||||
|
|
||||||
// Pointer to the status checker thread
|
// Pointer to the status checker thread
|
||||||
FPortalStatusChecker* StatusChecker;
|
FPortalStatusChecker* StatusChecker;
|
||||||
|
|
Loading…
Reference in a new issue