mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-02-05 07:45:40 +00:00
prelimary support for DDP sending - not tested outside simulator
* ddp send stub etc * queue * Update drv_ddp_send.c * sender * Update drv_ddp_send.c * q * enable * fx * test * fx * Update selftest_ws2812b.c * Update drv_ddpSend.c * Update drv_ddpSend.c * hder * test - will udp send adn receive work on github workflw? * better wait method for self test
This commit is contained in:
@ -214,6 +214,7 @@
|
||||
<ClCompile Include="src\driver\drv_cse7761.c" />
|
||||
<ClCompile Include="src\driver\drv_cse7766.c" />
|
||||
<ClCompile Include="src\driver\drv_ddp.c" />
|
||||
<ClCompile Include="src\driver\drv_ddpSend.c" />
|
||||
<ClCompile Include="src\driver\drv_debouncer.c" />
|
||||
<ClCompile Include="src\driver\drv_dht.c" />
|
||||
<ClCompile Include="src\driver\drv_dht_internal.c" />
|
||||
|
||||
@ -410,6 +410,7 @@
|
||||
<ClCompile Include="src\driver\drv_tca9554.c" />
|
||||
<ClCompile Include="src\driver\drv_leds_shared.c" />
|
||||
<ClCompile Include="src\driver\drv_dmx512.c" />
|
||||
<ClCompile Include="src\driver\drv_ddpSend.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\base64\base64.h" />
|
||||
|
||||
@ -21,8 +21,8 @@ static const char* group = "239.255.250.250";
|
||||
static int port = 4048;
|
||||
static int g_ddp_socket_receive = -1;
|
||||
static int g_retry_delay = 5;
|
||||
static int stat_packetsReceived = 0;
|
||||
static int stat_bytesReceived = 0;
|
||||
int stat_ddpPacketsReceived = 0;
|
||||
static int stat_ddpBytesReceived = 0;
|
||||
static char *g_ddp_buffer = 0;
|
||||
static int g_ddp_bufferSize = 512;
|
||||
|
||||
@ -184,12 +184,12 @@ void DRV_DDP_RunFrame() {
|
||||
}
|
||||
//addLogAdv(LOG_INFO, LOG_FEATURE_DDP,"Received %i bytes from %s\n",nbytes,inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr));
|
||||
|
||||
stat_packetsReceived++;
|
||||
stat_bytesReceived += nbytes;
|
||||
stat_ddpPacketsReceived++;
|
||||
stat_ddpBytesReceived += nbytes;
|
||||
|
||||
DDP_Parse((byte*)g_ddp_buffer, nbytes);
|
||||
|
||||
if (stat_packetsReceived % 10 == 0) {
|
||||
if (stat_ddpPacketsReceived % 10 == 0) {
|
||||
rtos_delay_milliseconds(5);
|
||||
}
|
||||
}
|
||||
@ -203,7 +203,7 @@ void DRV_DDP_Shutdown()
|
||||
}
|
||||
void DRV_DDP_AppendInformationToHTTPIndexPage(http_request_t* request)
|
||||
{
|
||||
hprintf255(request, "<h2>DDP received: %i packets, %i bytes</h2>", stat_packetsReceived, stat_bytesReceived);
|
||||
hprintf255(request, "<h2>DDP received: %i packets, %i bytes</h2>", stat_ddpPacketsReceived, stat_ddpBytesReceived);
|
||||
}
|
||||
void DRV_DDP_Init()
|
||||
{
|
||||
|
||||
197
src/driver/drv_ddpSend.c
Normal file
197
src/driver/drv_ddpSend.c
Normal file
@ -0,0 +1,197 @@
|
||||
|
||||
|
||||
#include "../new_common.h"
|
||||
#include "../new_pins.h"
|
||||
#include "../new_cfg.h"
|
||||
// Commands register, execution API and cmd tokenizer
|
||||
#include "../cmnds/cmd_public.h"
|
||||
#include "../driver/drv_public.h"
|
||||
#include "../logging/logging.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "../httpserver/new_http.h"
|
||||
#include "drv_local.h"
|
||||
#include "../quicktick.h"
|
||||
|
||||
|
||||
static int g_socket_ddpSend = -1;
|
||||
static int stat_sendBytes = 0;
|
||||
static int stat_sendPackets = 0;
|
||||
static int stat_failedPackets = 0;
|
||||
|
||||
typedef struct ddpQueueItem_s {
|
||||
int curSize;
|
||||
int totalSize;
|
||||
byte *data;
|
||||
int delay;
|
||||
struct sockaddr_in adr;
|
||||
struct ddpQueueItem_s *next;
|
||||
} ddpQueueItem_t;
|
||||
|
||||
ddpQueueItem_t *g_queue = 0;
|
||||
|
||||
int DRV_DDPSend_SendInternal(struct sockaddr_in *adr, const byte *frame, int numBytes) {
|
||||
int nbytes = sendto(
|
||||
g_socket_ddpSend,
|
||||
(const char*)frame,
|
||||
numBytes,
|
||||
0,
|
||||
(struct sockaddr*) adr,
|
||||
sizeof(*adr)
|
||||
);
|
||||
if (nbytes == numBytes) {
|
||||
stat_sendBytes += numBytes;
|
||||
stat_sendPackets++;
|
||||
return numBytes;
|
||||
}
|
||||
stat_failedPackets++;
|
||||
return 0;
|
||||
}
|
||||
void DRV_DDPSend_Send(const char *ip, int port, const byte *frame, int numBytes, int delay) {
|
||||
struct sockaddr_in adr;
|
||||
memset(&adr, 0, sizeof(adr));
|
||||
adr.sin_family = AF_INET;
|
||||
adr.sin_addr.s_addr = inet_addr(ip);
|
||||
adr.sin_port = htons(port);
|
||||
|
||||
if (delay <= 0) {
|
||||
DRV_DDPSend_SendInternal(&adr, frame, numBytes);
|
||||
return;
|
||||
}
|
||||
|
||||
ddpQueueItem_t *it = g_queue;
|
||||
while (it) {
|
||||
if (it->curSize == 0) {
|
||||
break; // found empty
|
||||
}
|
||||
it = it->next;
|
||||
}
|
||||
if (it == 0) {
|
||||
it = (ddpQueueItem_t*)malloc(sizeof(ddpQueueItem_t));
|
||||
if (it == 0) {
|
||||
// malloc failed
|
||||
return;
|
||||
}
|
||||
memset(it,0,sizeof(ddpQueueItem_t));
|
||||
it->adr = adr;
|
||||
it->totalSize = it->curSize = numBytes;
|
||||
it->data = malloc(numBytes);
|
||||
if (it->data == 0) {
|
||||
// malloc failed
|
||||
free(it);
|
||||
return;
|
||||
}
|
||||
it->next = g_queue;
|
||||
g_queue = it;
|
||||
}
|
||||
if (it->totalSize < numBytes) {
|
||||
byte *r = (byte*)realloc(it->data, numBytes);
|
||||
if (r == 0) {
|
||||
// realloc failed
|
||||
return;
|
||||
}
|
||||
it->data = r;
|
||||
it->totalSize = numBytes;
|
||||
}
|
||||
it->delay = delay;
|
||||
memcpy(it->data, frame, numBytes);
|
||||
it->curSize = numBytes;
|
||||
}
|
||||
void DRV_DDPSend_RunFrame() {
|
||||
ddpQueueItem_t *t;
|
||||
t = g_queue;
|
||||
while (t) {
|
||||
if (t->curSize > 0) {
|
||||
t->delay -= g_deltaTimeMS;
|
||||
if (t->delay <= 0) {
|
||||
int sendBytes = DRV_DDPSend_SendInternal(&t->adr, t->data, t->curSize);
|
||||
// TODO - do not clear if didn't send?
|
||||
t->curSize = 0; // mark as empty
|
||||
}
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
void DRV_DDPSend_Shutdown()
|
||||
{
|
||||
if (g_socket_ddpSend >= 0) {
|
||||
close(g_socket_ddpSend);
|
||||
g_socket_ddpSend = -1;
|
||||
}
|
||||
ddpQueueItem_t *it = g_queue;
|
||||
while (it) {
|
||||
ddpQueueItem_t *n = it->next;
|
||||
free(it->data);
|
||||
free(it);
|
||||
it = n;
|
||||
}
|
||||
g_queue = 0;
|
||||
}
|
||||
void DRV_DDPSend_AppendInformationToHTTPIndexPage(http_request_t* request)
|
||||
{
|
||||
hprintf255(request, "<h2>DDP sent: %i packets, %i bytes, errored packets: %i</h2>",
|
||||
stat_sendPackets, stat_sendBytes, stat_failedPackets);
|
||||
}
|
||||
|
||||
// ddp as in WLED
|
||||
#define DDP_TYPE_RGB24 0x0B // 00 001 011 (RGB , 8 bits per channel, 3 channels)
|
||||
#define DDP_TYPE_RGBW32 0x1B // 00 011 011 (RGBW, 8 bits per channel, 4 channels)
|
||||
#define DDP_FLAGS1_VER1 0x40 // version=1
|
||||
|
||||
// https://github.com/wled/WLED/blob/main/wled00/udp.cpp
|
||||
void DDP_SetHeader(byte *data, int pixelSize, int bytesCount) {
|
||||
// set ident
|
||||
data[0] = DDP_FLAGS1_VER1;
|
||||
|
||||
// set pixel size
|
||||
if (pixelSize == 4) {
|
||||
data[2] = DDP_TYPE_RGBW32;
|
||||
}
|
||||
else if (pixelSize == 3) {
|
||||
data[2] = DDP_TYPE_RGB24;
|
||||
}
|
||||
|
||||
// set bytes count
|
||||
data[8] = (byte)((bytesCount >> 8) & 0xFF); // MSB
|
||||
data[9] = (byte)(bytesCount & 0xFF); // LSB
|
||||
}
|
||||
commandResult_t DDP_Send(const void* context, const char* cmd, const char* args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
|
||||
if (Tokenizer_GetArgsCount() < 1) {
|
||||
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
}
|
||||
const char *ip = Tokenizer_GetArg(0);
|
||||
int host = Tokenizer_GetArgInteger(1);
|
||||
int pixelSize = Tokenizer_GetArgInteger(2);
|
||||
int delay = Tokenizer_GetArgInteger(3);
|
||||
const char *pData = Tokenizer_GetArg(4);
|
||||
int numBytes = strlen(pData) / 2;
|
||||
int headerSize = 10;
|
||||
byte *data = malloc(headerSize+numBytes);
|
||||
int cur = headerSize;
|
||||
while (*pData) {
|
||||
data[cur] = CMD_ParseOrExpandHexByte(&pData);
|
||||
cur++;
|
||||
}
|
||||
DDP_SetHeader(data, pixelSize, (cur- headerSize));
|
||||
DRV_DDPSend_Send(ip, host, data, cur, delay);
|
||||
free(data);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
void DRV_DDPSend_Init()
|
||||
{
|
||||
// create what looks like an ordinary UDP socket
|
||||
//
|
||||
g_socket_ddpSend = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (g_socket_ddpSend < 0) {
|
||||
g_socket_ddpSend = -1;
|
||||
addLogAdv(LOG_ERROR, LOG_FEATURE_HTTP, "DRV_DDPSend_Init: failed to do socket\n");
|
||||
return;
|
||||
}
|
||||
|
||||
CMD_RegisterCommand("DDP_Send", DDP_Send, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -224,6 +224,12 @@ void TCL_UART_RunEverySecond(void);
|
||||
void TCL_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState);
|
||||
void TCL_DoDiscovery(const char *topic);
|
||||
|
||||
void DRV_DDPSend_Init();
|
||||
void DRV_DDPSend_Shutdown();
|
||||
void DRV_DDPSend_RunFrame();
|
||||
void DRV_DDPSend_AppendInformationToHTTPIndexPage(http_request_t* request);
|
||||
|
||||
|
||||
#define SM2135_DELAY 4
|
||||
|
||||
// Software I2C
|
||||
|
||||
@ -315,7 +315,14 @@ static driver_t g_drivers[] = {
|
||||
#if ENABLE_DRIVER_IR2
|
||||
{ "IR2", DRV_IR2_Init, NULL, NULL, NULL, NULL, NULL, NULL, false },
|
||||
#endif
|
||||
|
||||
|
||||
#if ENABLE_DRIVER_DDPSEND
|
||||
//drvdetail:{"name":"DDPSend",
|
||||
//drvdetail:"title":"TODO",
|
||||
//drvdetail:"descr":"DDPqqqqqqq. See [DDP topic](https://www.elektroda.com/rtvforum/topic4040325.html)",
|
||||
//drvdetail:"requires":""}
|
||||
{ "DDPSend", DRV_DDPSend_Init, NULL, DRV_DDPSend_AppendInformationToHTTPIndexPage, DRV_DDPSend_RunFrame, DRV_DDPSend_Shutdown, NULL, NULL, false },
|
||||
#endif
|
||||
#if ENABLE_DRIVER_DDP
|
||||
//drvdetail:{"name":"DDP",
|
||||
//drvdetail:"title":"TODO",
|
||||
|
||||
@ -273,7 +273,6 @@ This platform is not supported, error!
|
||||
#include <limits.h>
|
||||
#define closesocket close
|
||||
#define SOCKET int
|
||||
#define closesocket close
|
||||
#define ISVALIDSOCKET(s) ((s) >= 0)
|
||||
#define GETSOCKETERRNO() (errno)
|
||||
#define ioctlsocket ioctl
|
||||
@ -286,6 +285,7 @@ This platform is not supported, error!
|
||||
|
||||
#else
|
||||
|
||||
#define close closesocket
|
||||
#define ISVALIDSOCKET(s) ((s) != INVALID_SOCKET)
|
||||
#define GETSOCKETERRNO() (WSAGetLastError())
|
||||
|
||||
|
||||
@ -163,6 +163,7 @@
|
||||
#define ENABLE_DRIVER_DRAWERS 1
|
||||
#define ENABLE_TASMOTA_JSON 1
|
||||
#define ENABLE_DRIVER_DDP 1
|
||||
#define ENABLE_DRIVER_DDPSEND 1
|
||||
#define ENABLE_DRIVER_SSDP 1
|
||||
#define ENABLE_DRIVER_ADCBUTTON 1
|
||||
#define ENABLE_DRIVER_SM15155E 1
|
||||
|
||||
@ -57,7 +57,7 @@ void Test_DMX_RGB() {
|
||||
|
||||
// nothing is sent by OBK at that point
|
||||
}
|
||||
void Test_DMX_RGBW() {
|
||||
void Test_DMX_RGBC() {
|
||||
// reset whole device
|
||||
SIM_ClearOBK(0);
|
||||
|
||||
@ -101,6 +101,62 @@ void Test_DMX_RGBW() {
|
||||
|
||||
// nothing is sent by OBK at that point
|
||||
}
|
||||
void Test_DMX_RGBW() {
|
||||
// reset whole device
|
||||
//SIM_ClearOBK(0);
|
||||
|
||||
//SIM_UART_InitReceiveRingBuffer(4096);
|
||||
//SIM_ClearUART();
|
||||
|
||||
//SELFTEST_ASSERT_HAS_UART_EMPTY();
|
||||
|
||||
//CMD_ExecuteCommand("startDriver DMX", 0);
|
||||
//CMD_ExecuteCommand("SM16703P_Init 3 RGBW", 0);
|
||||
//CMD_ExecuteCommand("SM16703P_SetPixel all 255 0 128 255", 0);
|
||||
//SELFTEST_ASSERT_PIXEL4(0, 255, 0, 128, 255);
|
||||
//SELFTEST_ASSERT_PIXEL4(1, 255, 0, 128, 255);
|
||||
//SELFTEST_ASSERT_PIXEL4(2, 255, 0, 128, 255);
|
||||
|
||||
//SELFTEST_ASSERT_HAS_UART_EMPTY();
|
||||
//CMD_ExecuteCommand("SM16703P_Start", 0);
|
||||
//SELFTEST_ASSERT_HAS_SOME_DATA_IN_UART();
|
||||
//SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 FF0080FF FF0080FF FF0080FF");
|
||||
//// 512 channels, but checked already 12
|
||||
//for (int i = 0; i < 100; i++) {
|
||||
// SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00 00 00");
|
||||
//}
|
||||
//SELFTEST_ASSERT_HAS_UART_EMPTY();
|
||||
|
||||
//CMD_ExecuteCommand("SM16703P_SetPixel 0 128 128 128 128", 0);
|
||||
//CMD_ExecuteCommand("SM16703P_SetPixel 1 255 255 255 255", 0);
|
||||
//CMD_ExecuteCommand("SM16703P_SetPixel 2 15 15 15 15", 0);
|
||||
//SELFTEST_ASSERT_PIXEL4(0, 128, 128, 128, 128);
|
||||
//SELFTEST_ASSERT_PIXEL4(1, 255, 255, 255, 255);
|
||||
//SELFTEST_ASSERT_PIXEL4(2, 15, 15, 15, 15);
|
||||
//SELFTEST_ASSERT_HAS_UART_EMPTY();
|
||||
//CMD_ExecuteCommand("SM16703P_Start", 0);
|
||||
//SELFTEST_ASSERT_HAS_SOME_DATA_IN_UART();
|
||||
//SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 80808080 FFFFFFFF 0F0F0F0F");
|
||||
//// 512 channels, but checked already 12
|
||||
//for (int i = 0; i < 100; i++) {
|
||||
// SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00 00 00");
|
||||
//}
|
||||
//SELFTEST_ASSERT_HAS_UART_EMPTY();
|
||||
|
||||
// nothing is sent by OBK at that point
|
||||
}
|
||||
extern int stat_ddpPacketsReceived;
|
||||
void SIM_WaitForDDPPacket() {
|
||||
int prev = stat_ddpPacketsReceived;
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Sim_RunFrames(1, true);
|
||||
if (stat_ddpPacketsReceived > prev) {
|
||||
break; // got it
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void Test_WS2812B() {
|
||||
// reset whole device
|
||||
SIM_ClearOBK(0);
|
||||
@ -230,6 +286,27 @@ void Test_WS2812B() {
|
||||
SELFTEST_ASSERT_PIXEL(1, 0xFF, 0, 0);
|
||||
SELFTEST_ASSERT_PIXEL(2, 0xFF, 0, 0xFF);
|
||||
}
|
||||
CMD_ExecuteCommand("startDriver DDP", 0);
|
||||
CMD_ExecuteCommand("startDriver DDPSend", 0);
|
||||
CMD_ExecuteCommand("DDP_Send 127.0.0.1 4048 3 0 FF00AB", 0);
|
||||
SIM_WaitForDDPPacket();
|
||||
// this requires udp to work so it can pass...
|
||||
if (1) {
|
||||
SELFTEST_ASSERT_PIXEL(0, 0xFF, 0x00, 0xAB);
|
||||
}
|
||||
CMD_ExecuteCommand("DDP_Send 127.0.0.1 4048 3 0 ABCDEF", 0);
|
||||
SIM_WaitForDDPPacket();
|
||||
if (1) {
|
||||
SELFTEST_ASSERT_PIXEL(0, 0xAB, 0xCD, 0xEF);
|
||||
}
|
||||
CMD_ExecuteCommand("DDP_Send 127.0.0.1 4048 3 0 ABCDEFAABBCC", 0);
|
||||
SIM_WaitForDDPPacket();
|
||||
if (1) {
|
||||
SELFTEST_ASSERT_PIXEL(0, 0xAB, 0xCD, 0xEF);
|
||||
SELFTEST_ASSERT_PIXEL(1, 0xAA, 0xBB, 0xCC);
|
||||
}
|
||||
|
||||
|
||||
// fake DDP RGBW packet
|
||||
{
|
||||
byte ddpPacket[128];
|
||||
@ -348,6 +425,7 @@ void Test_WS2812B() {
|
||||
|
||||
void Test_LEDstrips() {
|
||||
Test_DMX_RGB();
|
||||
Test_DMX_RGBC();
|
||||
Test_DMX_RGBW();
|
||||
Test_WS2812B();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user