Skip to content

Commit

Permalink
chuni-io: v1.0. led support, more ir sensors.
Browse files Browse the repository at this point in the history
  • Loading branch information
magicnat committed Feb 1, 2020
1 parent 99e1105 commit bd325d8
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 95 deletions.
54 changes: 45 additions & 9 deletions ChuniVController/ChuniIO/chuniio.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ static HANDLE chuni_io_slider_thread;
static bool chuni_io_slider_stop_flag;
static SOCKET chuni_socket;
static USHORT chuni_port = 24864; // CHUNI on dialpad
static struct sockaddr_in remote;
static bool remote_exist = false;

HRESULT chuni_io_jvs_init(void)
{
Expand Down Expand Up @@ -139,11 +141,29 @@ void chuni_io_slider_stop(void)

void chuni_io_slider_set_leds(const uint8_t* rgb)
{
static uint8_t prev_rgb_status[32];

for (uint8_t i = 0; i < 32; i++) {
if (rgb[i] != prev_rgb_status[i]) log_debug("SET_LED[%d]: %d\n", i, rgb[i]);
static uint8_t prev_rgb_status[96];
static chuni_msg_t message;
message.src = SRC_GAME;
message.type = LED_SET;

// ignore odd, since no 1/32 color strip exist.
for (uint8_t i = 0; i < 96; i += 6) {
if (rgb[i] != prev_rgb_status[i] || rgb[i + 1] != prev_rgb_status[i + 1] || rgb[i + 2] != prev_rgb_status[i + 2]) {
uint8_t n = i / 6;
log_debug("SET_LED[%d]: rgb(%d, %d, %d)\n", n, rgb[i + 1], rgb[i + 2], rgb[i]);
if (!remote_exist) log_warn("remote does not exist.\n");
else {
message.target = n;
message.led_color_r = rgb[i + 1];
message.led_color_g = rgb[i + 2];
message.led_color_b = rgb[i];
sendto(chuni_socket, (const char*)&message, sizeof(chuni_msg_t), 0, (const sockaddr*)&remote, sizeof(struct sockaddr_in));
}
}

prev_rgb_status[i] = rgb[i];
prev_rgb_status[i + 1] = rgb[i + 1];
prev_rgb_status[i + 2] = rgb[i + 2];
}
}

Expand All @@ -159,7 +179,10 @@ static unsigned int __stdcall chuni_io_slider_thread_proc(void* ctx)
callback = (chuni_io_slider_callback_t) ctx;

while (!chuni_io_slider_stop_flag) {
int len = recv(chuni_socket, recv_buf, 32, 0); // FIXME: discard pending data on proc start
int addr_sz = sizeof(struct sockaddr_in);
// FIXME: discard pending data on proc start?
int len = recvfrom(chuni_socket, recv_buf, 32, 0, (sockaddr*)&remote, &addr_sz);
remote_exist = true;
if (len == (int) sizeof(chuni_msg_t)) {
const chuni_msg_t* msg = (const chuni_msg_t*)recv_buf;
if (msg->src != SRC_CONTROLLER) {
Expand All @@ -169,27 +192,40 @@ static unsigned int __stdcall chuni_io_slider_thread_proc(void* ctx)
}
switch (msg->type) {
case COIN_INSERT:
log_debug("adding coin.\n");
chuni_coin_pending = true;
break;
case SLIDER_PRESS:
if (msg->target >= 32) log_error("invalid slider value %d in SLIDER_PRESS.\n", msg->target);
else pressure[msg->target] = 128;
log_debug("slider_press at %d.\n", msg->target);
if (msg->target >= 16) log_error("invalid slider value %d in SLIDER_PRESS.\n", msg->target);
else {
pressure[(msg->target) * 2] = 128;
pressure[(msg->target) * 2 + 1] = 128;
}
break;
case SLIDER_RELEASE:
if (msg->target >= 32) log_error("invalid slider value %d in SLIDER_RELEASE.\n", msg->target);
else pressure[msg->target] = 0;
log_debug("slider released on %d.\n", msg->target);
if (msg->target >= 16) log_error("invalid slider value %d in SLIDER_RELEASE.\n", msg->target);
else {
pressure[(msg->target) * 2] = 0;
pressure[(msg->target) * 2 + 1] = 0;
}
break;
case CABINET_TEST:
log_debug("setting cabinet_test.\n");
chuni_test_pending = true;
break;
case CABINET_SERVICE:
log_debug("setting cabinet_service.\n");
chuni_service_pending = true;
break;
case IR_BLOCKED:
log_debug("ir %d blokced.\n", msg->target);
if (msg->target >= 6) log_error("invalid slider value %d in IR_BLOCKED.\n", msg->target);
else chuni_ir_sensor_map |= 1 << msg->target;
break;
case IR_UNBLOCKED:
log_debug("ir %d unblokced.\n", msg->target);
if (msg->target >= 6) log_error("invalid slider value %d in IR_UNBLOCKED.\n", msg->target);
else chuni_ir_sensor_map &= ~(1 << msg->target);
break;
Expand Down
12 changes: 7 additions & 5 deletions ChuniVController/ChuniIO/chuniio.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
#endif

typedef enum {
SRC_GAME,
SRC_CONTROLLER
SRC_GAME = 0 ,
SRC_CONTROLLER = 1
} chuni_msg_src_t;

typedef enum {
Expand All @@ -23,14 +23,16 @@ typedef enum {
} chuni_msg_type_t;

typedef struct {
chuni_msg_src_t src;
chuni_msg_type_t type;
uint8_t src;
uint8_t type;

// For SLIDER_*, IR_* and LED_SET. Index of the target SLIDER/LED/IR_SENSOR
uint8_t target;

// for LED_SET only
uint32_t led_color;
uint8_t led_color_r;
uint8_t led_color_g;
uint8_t led_color_b;
} chuni_msg_t;

typedef void (*chuni_io_slider_callback_t)(const uint8_t* state);
Expand Down
17 changes: 0 additions & 17 deletions ChuniVController/ChuniVController/App.xaml.cs

This file was deleted.

167 changes: 167 additions & 0 deletions ChuniVController/ChuniVController/ChuniIO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;

namespace ChuniVController
{
public enum ChuniMessageSources
{
Game = 0,
Controller = 1
}

public enum ChuniMessageTypes
{
CoinInsert = 0,
SliderPress = 1,
SliderRelease = 2,
LedSet = 3,
CabinetTest = 4,
CabinetService = 5,
IrBlocked = 6,
IrUnblocked = 7
}

public struct ChuniIoMessage
{
public byte Source;
public byte Type;
public byte Target;
public byte LedColorRed;
public byte LedColorGreen;
public byte LedColorBlue;
}

public class ChuniIO
{
private readonly UdpClient _client;
private readonly string _ioServerAddress;
private readonly int _port;
private bool _running;
private byte[] _sendBuffer;
private readonly IntPtr _sendBufferUnmanaged;
private readonly RecvCallback _recvCallback;
private Thread _recvThread;

private struct RecvContext
{
public UdpClient client;
public RecvCallback callback;
}

public delegate void RecvCallback(ChuniIoMessage message);

public ChuniIO(string ioServerAddress, int port, RecvCallback recvCallback)
{
_ioServerAddress = ioServerAddress;
_port = port;
_running = false;
_client = new UdpClient();
_sendBuffer = new byte[32];
_sendBufferUnmanaged = Marshal.AllocHGlobal(32);

_recvCallback = recvCallback;
}

~ChuniIO()
{
Marshal.FreeHGlobal(_sendBufferUnmanaged);
}

private static void RecvThread(object c)
{
ChuniIoMessage message = new ChuniIoMessage();
int sz = Marshal.SizeOf(message);
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
IntPtr recvBufferPtr;
recvBufferPtr = Marshal.AllocHGlobal(32);

RecvContext context = (RecvContext) c;

try
{
while (true)
{
byte[] recvBuffer = context.client.Receive(ref endpoint);
if (recvBuffer.Length == 0) break;
if (recvBuffer.Length != sz) continue;
Marshal.Copy(recvBuffer, 0, recvBufferPtr, sz);
message = (ChuniIoMessage)Marshal.PtrToStructure(recvBufferPtr, message.GetType());
context.callback(message);
}
}
catch
{
// noting, just exit.
}


Marshal.FreeHGlobal(recvBufferPtr);
}

public bool Start()
{
if (_running) return false;
try
{
_client.Connect(_ioServerAddress, _port);
}
catch
{
return false;
}

RecvContext c = new RecvContext();
c.client = _client;
c.callback = _recvCallback;

_recvThread = new Thread(RecvThread);
_recvThread.Start(c);

_running = true;
return true;
}

public bool Stop()
{
if (!_running) return false;
try
{
_client.Close();
}
catch
{
return false;
}
return true;
}

public void Join()
{
_recvThread.Join();
}

private void SendCallback(IAsyncResult ar)
{
// don't care
}

public void Send(ChuniIoMessage message)
{
int sz = Marshal.SizeOf(message);
Marshal.StructureToPtr(message, _sendBufferUnmanaged, false);
Marshal.Copy(_sendBufferUnmanaged, _sendBuffer, 0, sz);
_client.BeginSend(_sendBuffer, sz, SendCallback, null);
}



}
}
5 changes: 1 addition & 4 deletions ChuniVController/ChuniVController/ChuniVController.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,14 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="ChuniIO.cs" />
<Compile Include="TouchPad.xaml.cs">
<DependentUpon>TouchPad.xaml</DependentUpon>
</Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
Expand Down
Loading

0 comments on commit bd325d8

Please sign in to comment.