beta with artnet protocol
This commit is contained in:
parent
a01770282d
commit
e8b99665be
149
RpiLedBars/.clang-format
Normal file
149
RpiLedBars/.clang-format
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveMacros: false
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveBitFields: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: Align
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllConstructorInitializersOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: Never
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 100
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DeriveLineEnding: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||||
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IncludeIsMainSourceRegex: ''
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentGotoLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentExternBlock: AfterExternBlock
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
InsertTrailingCommas: None
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
Standard: Latest
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 8
|
||||||
|
UseCRLF: false
|
||||||
|
UseTab: Never
|
||||||
|
WhitespaceSensitiveMacros:
|
||||||
|
- STRINGIZE
|
||||||
|
- PP_STRINGIZE
|
||||||
|
- BOOST_PP_STRINGIZE
|
||||||
|
...
|
||||||
|
|
2
RpiLedBars/.gitignore
vendored
Normal file
2
RpiLedBars/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
bin
|
||||||
|
obj
|
31
RpiLedBars/.vscode/launch.json
vendored
Normal file
31
RpiLedBars/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "(gdb) Launch",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/bin/pixled",
|
||||||
|
"args": [
|
||||||
|
"-n", "5",
|
||||||
|
// "-t"
|
||||||
|
],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"environment": [],
|
||||||
|
"externalConsole": false,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"miDebuggerPath": "${workspaceFolder}/sgdb.sh"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"type": "cppbuild",
|
"type": "shell",
|
||||||
"label": "Build project",
|
"label": "Build project",
|
||||||
"command": "make",
|
"command": "make",
|
||||||
"options": {
|
"options": {
|
||||||
@ -15,6 +15,10 @@
|
|||||||
"kind": "build",
|
"kind": "build",
|
||||||
"isDefault": true
|
"isDefault": true
|
||||||
},
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "new"
|
||||||
|
},
|
||||||
"detail": "compiler: /usr/bin/gcc"
|
"detail": "compiler: /usr/bin/gcc"
|
||||||
},
|
},
|
||||||
{
|
{
|
@ -1,5 +1,5 @@
|
|||||||
CC=gcc
|
CC=gcc
|
||||||
CFLAGS=-Wall -g -DDEBUG
|
CFLAGS=-Wall -g #-DDEBUG
|
||||||
LDFLAGS=#-lpthread
|
LDFLAGS=#-lpthread
|
||||||
SRCDIR=src
|
SRCDIR=src
|
||||||
OBJDIR=obj
|
OBJDIR=obj
|
||||||
@ -8,7 +8,7 @@ SRC=$(notdir $(wildcard $(SRCDIR)/*.c))
|
|||||||
OBJ=$(SRC:.c=.o)
|
OBJ=$(SRC:.c=.o)
|
||||||
BIN=pixled
|
BIN=pixled
|
||||||
|
|
||||||
all: $(addprefix $(BINDIR)/, $(BIN))
|
all: clean $(addprefix $(BINDIR)/, $(BIN))
|
||||||
|
|
||||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||||
if [ ! -d $(OBJDIR) ]; then mkdir "$(OBJDIR)"; fi
|
if [ ! -d $(OBJDIR) ]; then mkdir "$(OBJDIR)"; fi
|
||||||
@ -20,4 +20,5 @@ $(BINDIR)/$(BIN) : $(addprefix $(OBJDIR)/, $(OBJ))
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BINDIR)/* $(OBJDIR)/*
|
rm -rf $(BINDIR)/* $(OBJDIR)/*
|
||||||
rmdir $(BINDIR) $(OBJDIR)
|
if [ -d $(OBJDIR) ]; then rmdir "$(OBJDIR)"; fi
|
||||||
|
if [ -d "$(BINDIR)" ]; then rmdir "$(BINDIR)"; fi
|
3
RpiLedBars/sgdb.sh
Executable file
3
RpiLedBars/sgdb.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
sudo /usr/bin/gdb "$@"
|
@ -16,7 +16,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Location of peripheral registers in physical memory
|
// Location of peripheral registers in physical memory
|
||||||
#define PHYS_REG_BASE PI_01_REG_BASE
|
#define PHYS_REG_BASE PI_23_REG_BASE
|
||||||
#define PI_01_REG_BASE 0x20000000 // Pi Zero or 1
|
#define PI_01_REG_BASE 0x20000000 // Pi Zero or 1
|
||||||
#define PI_23_REG_BASE 0x3F000000 // Pi 2 or 3
|
#define PI_23_REG_BASE 0x3F000000 // Pi 2 or 3
|
||||||
#define PI_4_REG_BASE 0xFE000000 // Pi 4
|
#define PI_4_REG_BASE 0xFE000000 // Pi 4
|
||||||
|
@ -30,17 +30,20 @@
|
|||||||
// v0.11 JPB 29/9/20 Added enable_dma before transfer (in case still active)
|
// v0.11 JPB 29/9/20 Added enable_dma before transfer (in case still active)
|
||||||
// Corrected DMA nsamp value (was byte count)
|
// Corrected DMA nsamp value (was byte count)
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include "rpi_dma_utils.h"
|
#include "rpi_dma_utils.h"
|
||||||
#include "rpi_smi_defs.h"
|
#include "rpi_smi_defs.h"
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#if PHYS_REG_BASE==PI_4_REG_BASE // Timings for RPi v4 (1.5 GHz)
|
#if PHYS_REG_BASE == PI_4_REG_BASE // Timings for RPi v4 (1.5 GHz)
|
||||||
#define SMI_TIMING 10, 15, 30, 15 // 400 ns cycle time
|
#define SMI_TIMING 10, 15, 30, 15 // 400 ns cycle time
|
||||||
#else // Timings for RPi v0-3 (1 GHz)
|
#else // Timings for RPi v0-3 (1 GHz)
|
||||||
#define SMI_TIMING 10, 10, 20, 10 // 400 ns cycle time
|
#define SMI_TIMING 10, 10, 20, 10 // 400 ns cycle time
|
||||||
@ -92,11 +95,11 @@ volatile SMI_DCD_REG *smi_dcd;
|
|||||||
#define TX_BUFF_SIZE(n) (TX_BUFF_LEN(n) * sizeof(TXDATA_T))
|
#define TX_BUFF_SIZE(n) (TX_BUFF_LEN(n) * sizeof(TXDATA_T))
|
||||||
#define VC_MEM_SIZE (PAGE_SIZE + TX_BUFF_SIZE(CHAN_MAXLEDS))
|
#define VC_MEM_SIZE (PAGE_SIZE + TX_BUFF_SIZE(CHAN_MAXLEDS))
|
||||||
|
|
||||||
|
const char artnetId[] = "Art-Net";
|
||||||
|
|
||||||
// RGB values for test mode (1 value for each of 16 channels)
|
// RGB values for test mode (1 value for each of 16 channels)
|
||||||
int on_rgbs[16] = {0xff0000, 0x00ff00, 0x0000ff, 0xffffff,
|
int on_rgbs[16] = {0xff0000, 0x00ff00, 0x0000ff, 0xffffff, 0xff4040, 0x40ff40, 0x4040ff, 0x404040,
|
||||||
0xff4040, 0x40ff40, 0x4040ff, 0x404040,
|
0xff0000, 0x00ff00, 0x0000ff, 0xffffff, 0xff4040, 0x40ff40, 0x4040ff, 0x404040};
|
||||||
0xff0000, 0x00ff00, 0x0000ff, 0xffffff,
|
|
||||||
0xff4040, 0x40ff40, 0x4040ff, 0x404040};
|
|
||||||
int off_rgbs[16];
|
int off_rgbs[16];
|
||||||
|
|
||||||
#if TX_TEST
|
#if TX_TEST
|
||||||
@ -106,9 +109,10 @@ TXDATA_T tx_test_data[] = {1, 2, 3, 4, 5, 6, 7, 0};
|
|||||||
|
|
||||||
TXDATA_T *txdata; // Pointer to uncached Tx data buffer
|
TXDATA_T *txdata; // Pointer to uncached Tx data buffer
|
||||||
TXDATA_T tx_buffer[TX_BUFF_LEN(CHAN_MAXLEDS)]; // Tx buffer for assembling data
|
TXDATA_T tx_buffer[TX_BUFF_LEN(CHAN_MAXLEDS)]; // Tx buffer for assembling data
|
||||||
int testmode, chan_ledcount=1; // Command-line parameters
|
int testmode, chan_ledcount = 1; // Command-line parameters
|
||||||
int rgb_data[CHAN_MAXLEDS][LED_NCHANS]; // RGB data
|
int rgb_data[CHAN_MAXLEDS][LED_NCHANS]; // RGB data
|
||||||
int chan_num; // Current channel for data I/P
|
int chan_num; // Current channel for data I/P
|
||||||
|
int udpSocket;
|
||||||
|
|
||||||
void rgb_txdata(int *rgbs, TXDATA_T *txd);
|
void rgb_txdata(int *rgbs, TXDATA_T *txd);
|
||||||
int str_rgb(char *s, int rgbs[][LED_NCHANS], int chan);
|
int str_rgb(char *s, int rgbs[][LED_NCHANS], int chan);
|
||||||
@ -121,18 +125,17 @@ void init_smi(int width, int ns, int setup, int hold, int strobe);
|
|||||||
void setup_smi_dma(MEM_MAP *mp, int nsamp);
|
void setup_smi_dma(MEM_MAP *mp, int nsamp);
|
||||||
void start_smi(MEM_MAP *mp);
|
void start_smi(MEM_MAP *mp);
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[]) {
|
||||||
{
|
// setup
|
||||||
int args=0, n, oset=0;
|
int args = 0, n, oset = 0;
|
||||||
|
memset(off_rgbs, 0, sizeof(int) * 16);
|
||||||
|
|
||||||
while (argc > ++args) // Process command-line args
|
while (argc > ++args) // Process command-line args
|
||||||
{
|
{
|
||||||
if (argv[args][0] == '-')
|
if (argv[args][0] == '-') {
|
||||||
{
|
switch (toupper(argv[args][1])) {
|
||||||
switch (toupper(argv[args][1]))
|
|
||||||
{
|
|
||||||
case 'N': // -N: number of LEDs per channel
|
case 'N': // -N: number of LEDs per channel
|
||||||
if (args >= argc-1)
|
if (args >= argc - 1)
|
||||||
fprintf(stderr, "Error: no numeric value\n");
|
fprintf(stderr, "Error: no numeric value\n");
|
||||||
else
|
else
|
||||||
chan_ledcount = atoi(argv[++args]);
|
chan_ledcount = atoi(argv[++args]);
|
||||||
@ -143,51 +146,56 @@ int main(int argc, char *argv[])
|
|||||||
default: // Otherwise error
|
default: // Otherwise error
|
||||||
printf("Unrecognised option '%c'\n", argv[args][1]);
|
printf("Unrecognised option '%c'\n", argv[args][1]);
|
||||||
printf("Options:\n"
|
printf("Options:\n"
|
||||||
" -n num number of LEDs per channel\n"\
|
" -n num number of LEDs per channel\n"
|
||||||
" -t Test mode (flash LEDs)\n"\
|
" -t Test mode (flash LEDs)\n");
|
||||||
);
|
return (1);
|
||||||
return(1);
|
|
||||||
}
|
}
|
||||||
}
|
} else if (chan_num < LED_NCHANS && hexdig(argv[args][0]) >= 0 &&
|
||||||
else if (chan_num<LED_NCHANS && hexdig(argv[args][0])>=0 &&
|
(n = str_rgb(argv[args], rgb_data, chan_num)) > 0) {
|
||||||
(n=str_rgb(argv[args], rgb_data, chan_num))>0)
|
|
||||||
{
|
|
||||||
chan_ledcount = n > chan_ledcount ? n : chan_ledcount;
|
chan_ledcount = n > chan_ledcount ? n : chan_ledcount;
|
||||||
chan_num++;
|
chan_num++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signal(SIGINT, terminate);
|
signal(SIGINT, terminate);
|
||||||
map_devices();
|
map_devices();
|
||||||
init_smi(LED_NCHANS>8 ? SMI_16_BITS : SMI_8_BITS, SMI_TIMING);
|
init_smi(LED_NCHANS > 8 ? SMI_16_BITS : SMI_8_BITS, SMI_TIMING);
|
||||||
map_uncached_mem(&vc_mem, VC_MEM_SIZE);
|
map_uncached_mem(&vc_mem, VC_MEM_SIZE);
|
||||||
#if TX_TEST
|
|
||||||
oset = oset;
|
|
||||||
setup_smi_dma(&vc_mem, sizeof(tx_test_data)/sizeof(TXDATA_T));
|
|
||||||
#if LED_NCHANS <= 8
|
|
||||||
swap_bytes(tx_test_data, sizeof(tx_test_data));
|
|
||||||
#endif
|
|
||||||
memcpy(txdata, tx_test_data, sizeof(tx_test_data));
|
|
||||||
start_smi(&vc_mem);
|
|
||||||
usleep(10);
|
|
||||||
while (dma_active(DMA_CHAN))
|
|
||||||
usleep(10);
|
|
||||||
#else
|
|
||||||
setup_smi_dma(&vc_mem, TX_BUFF_LEN(chan_ledcount));
|
|
||||||
printf("%s %u LED%s per channel, %u channels\n", testmode ? "Testing" : "Setting",
|
|
||||||
chan_ledcount, chan_ledcount==1 ? "" : "s", LED_NCHANS);
|
|
||||||
|
|
||||||
if (testmode)
|
setup_smi_dma(&vc_mem, TX_BUFF_LEN(chan_ledcount));
|
||||||
{
|
printf("%s %u LED%s per channel, %u channels\n", testmode ? "Testing" : "Setting", chan_ledcount,
|
||||||
while (1)
|
chan_ledcount == 1 ? "" : "s", LED_NCHANS);
|
||||||
{
|
|
||||||
|
int nBytes;
|
||||||
|
char buffer[1024];
|
||||||
|
struct sockaddr_in serverAddr;
|
||||||
|
struct sockaddr_storage serverStorage;
|
||||||
|
socklen_t addr_size;
|
||||||
|
|
||||||
|
/*Create UDP socket*/
|
||||||
|
udpSocket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
|
/*Configure settings in address struct*/
|
||||||
|
serverAddr.sin_family = AF_INET;
|
||||||
|
serverAddr.sin_port = htons(0x1936);
|
||||||
|
serverAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
|
||||||
|
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
|
||||||
|
|
||||||
|
/*Bind socket with address struct*/
|
||||||
|
bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
|
||||||
|
|
||||||
|
/*Initialize size variable to be used later on*/
|
||||||
|
addr_size = sizeof serverStorage;
|
||||||
|
|
||||||
|
memcpy(txdata, tx_buffer, TX_BUFF_SIZE(chan_ledcount));
|
||||||
|
start_smi(&vc_mem);
|
||||||
|
// loops
|
||||||
|
if (testmode) {
|
||||||
|
while (1) {
|
||||||
if (chan_ledcount < 2)
|
if (chan_ledcount < 2)
|
||||||
rgb_txdata(oset&1 ? off_rgbs : on_rgbs, tx_buffer);
|
rgb_txdata(oset & 1 ? off_rgbs : on_rgbs, tx_buffer);
|
||||||
else
|
else {
|
||||||
{
|
for (n = 0; n < chan_ledcount; n++) {
|
||||||
for (n=0; n<chan_ledcount; n++)
|
rgb_txdata(n == oset % chan_ledcount ? on_rgbs : off_rgbs, &tx_buffer[LED_TX_OSET(n)]);
|
||||||
{
|
|
||||||
rgb_txdata(n==oset%chan_ledcount ? on_rgbs : off_rgbs,
|
|
||||||
&tx_buffer[LED_TX_OSET(n)]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oset++;
|
oset++;
|
||||||
@ -198,58 +206,73 @@ int main(int argc, char *argv[])
|
|||||||
start_smi(&vc_mem);
|
start_smi(&vc_mem);
|
||||||
usleep(CHASE_MSEC * 1000);
|
usleep(CHASE_MSEC * 1000);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
while (1) {
|
||||||
|
nBytes = recvfrom(udpSocket, buffer, 1024, 0, (struct sockaddr *)&serverStorage, &addr_size);
|
||||||
|
if (nBytes <= 530 && nBytes > 0) {
|
||||||
|
if (memcmp(buffer, artnetId, sizeof(artnetId)) == 0) {
|
||||||
|
uint16_t opcode = buffer[8] | (buffer[9] << 8);
|
||||||
|
if (opcode == 0x5000) {
|
||||||
|
// uint8_t sequence = buffer[12];
|
||||||
|
// uint16_t incomingUniverse = buffer[14] | (buffer[15] << 8);
|
||||||
|
uint16_t dmxDataLength = buffer[17] | (buffer[16] << 8);
|
||||||
|
char *dmxData = buffer + 18;
|
||||||
|
uint16_t maxBound =
|
||||||
|
(dmxDataLength / 3) < chan_ledcount ? (dmxDataLength / 3) : chan_ledcount;
|
||||||
|
for (size_t i = 0; i < maxBound; ++i) {
|
||||||
|
for (size_t j = 0; j < LED_NCHANS; ++j) {
|
||||||
|
char *rgb = dmxData + (i * 3);
|
||||||
|
rgb_data[i][j] = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
|
||||||
}
|
}
|
||||||
else
|
rgb_txdata(rgb_data[i], &tx_buffer[LED_TX_OSET(i)]);
|
||||||
{
|
}
|
||||||
for (n=0; n<chan_ledcount; n++)
|
|
||||||
rgb_txdata(rgb_data[n], &tx_buffer[LED_TX_OSET(n)]);
|
|
||||||
#if LED_NCHANS <= 8
|
#if LED_NCHANS <= 8
|
||||||
swap_bytes(tx_buffer, TX_BUFF_SIZE(chan_ledcount));
|
swap_bytes(tx_buffer, TX_BUFF_SIZE(chan_ledcount));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memcpy(txdata, tx_buffer, TX_BUFF_SIZE(chan_ledcount));
|
memcpy(txdata, tx_buffer, TX_BUFF_SIZE(chan_ledcount));
|
||||||
enable_dma(DMA_CHAN);
|
// enable_dma(DMA_CHAN);
|
||||||
start_smi(&vc_mem);
|
start_smi(&vc_mem);
|
||||||
usleep(10);
|
// usleep(10);
|
||||||
while (dma_active(DMA_CHAN))
|
// while (dma_active(DMA_CHAN))
|
||||||
usleep(10);
|
// usleep(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
terminate(0);
|
terminate(0);
|
||||||
return(0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert RGB text string into integer data, for given channel
|
// Convert RGB text string into integer data, for given channel
|
||||||
// Return number of data points for this channel
|
// Return number of data points for this channel
|
||||||
int str_rgb(char *s, int rgbs[][LED_NCHANS], int chan)
|
int str_rgb(char *s, int rgbs[][LED_NCHANS], int chan) {
|
||||||
{
|
int i = 0;
|
||||||
int i=0;
|
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
while (chan<LED_NCHANS && i<CHAN_MAXLEDS && hexdig(*s)>=0)
|
while (chan < LED_NCHANS && i < CHAN_MAXLEDS && hexdig(*s) >= 0) {
|
||||||
{
|
|
||||||
rgbs[i++][chan] = strtoul(s, &p, 16);
|
rgbs[i++][chan] = strtoul(s, &p, 16);
|
||||||
s = *p ? p+1 : p;
|
s = *p ? p + 1 : p;
|
||||||
}
|
}
|
||||||
return(i);
|
return (i);
|
||||||
}
|
}
|
||||||
// Set Tx data for 8 or 16 chans, 1 LED per chan, given 1 RGB val per chan
|
// Set Tx data for 8 or 16 chans, 1 LED per chan, given 1 RGB val per chan
|
||||||
// Logic 1 is 0.8us high, 0.4 us low, logic 0 is 0.4us high, 0.8us low
|
// Logic 1 is 0.8us high, 0.4 us low, logic 0 is 0.4us high, 0.8us low
|
||||||
void rgb_txdata(int *rgbs, TXDATA_T *txd)
|
void rgb_txdata(int *rgbs, TXDATA_T *txd) {
|
||||||
{
|
|
||||||
int i, n, msk;
|
int i, n, msk;
|
||||||
|
|
||||||
// For each bit of the 24-bit RGB values..
|
// For each bit of the 24-bit RGB values..
|
||||||
for (n=0; n<LED_NBITS; n++)
|
for (n = 0; n < LED_NBITS; n++) {
|
||||||
{
|
|
||||||
// Mask to convert RGB to GRB, M.S bit first
|
// Mask to convert RGB to GRB, M.S bit first
|
||||||
msk = n==0 ? 0x8000 : n==8 ? 0x800000 : n==16 ? 0x80 : msk>>1;
|
msk = n == 0 ? 0x8000 : n == 8 ? 0x800000 : n == 16 ? 0x80 : msk >> 1;
|
||||||
// 1st byte or word is a high pulse on all lines
|
// 1st byte or word is a high pulse on all lines
|
||||||
txd[0] = (TXDATA_T)0xffff;
|
txd[0] = (TXDATA_T)0xffff;
|
||||||
// 2nd has high or low bits from data
|
// 2nd has high or low bits from data
|
||||||
// 3rd is a low pulse
|
// 3rd is a low pulse
|
||||||
txd[1] = txd[2] = 0;
|
txd[1] = txd[2] = 0;
|
||||||
for (i=0; i<LED_NCHANS; i++)
|
for (i = 0; i < LED_NCHANS; i++) {
|
||||||
{
|
|
||||||
if (rgbs[i] & msk)
|
if (rgbs[i] & msk)
|
||||||
txd[1] |= (1 << i);
|
txd[1] |= (1 << i);
|
||||||
}
|
}
|
||||||
@ -258,29 +281,25 @@ void rgb_txdata(int *rgbs, TXDATA_T *txd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Swap adjacent bytes in transmit data
|
// Swap adjacent bytes in transmit data
|
||||||
void swap_bytes(void *data, int len)
|
void swap_bytes(void *data, int len) {
|
||||||
{
|
|
||||||
uint16_t *wp = (uint16_t *)data;
|
uint16_t *wp = (uint16_t *)data;
|
||||||
|
|
||||||
len = (len + 1) / 2;
|
len = (len + 1) / 2;
|
||||||
while (len-- > 0)
|
while (len-- > 0) {
|
||||||
{
|
|
||||||
*wp = __builtin_bswap16(*wp);
|
*wp = __builtin_bswap16(*wp);
|
||||||
wp++;
|
wp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return hex digit value, -ve if not hex
|
// Return hex digit value, -ve if not hex
|
||||||
int hexdig(char c)
|
int hexdig(char c) {
|
||||||
{
|
|
||||||
c = toupper(c);
|
c = toupper(c);
|
||||||
return((c>='0' && c<='9') ? c-'0' : (c>='A' && c<='F') ? c-'A'+10 : -1);
|
return ((c >= '0' && c <= '9') ? c - '0' : (c >= 'A' && c <= 'F') ? c - 'A' + 10 : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map GPIO, DMA and SMI registers into virtual mem (user space)
|
// Map GPIO, DMA and SMI registers into virtual mem (user space)
|
||||||
// If any of these fail, program will be terminated
|
// If any of these fail, program will be terminated
|
||||||
void map_devices(void)
|
void map_devices(void) {
|
||||||
{
|
|
||||||
map_periph(&gpio_regs, (void *)GPIO_BASE, PAGE_SIZE);
|
map_periph(&gpio_regs, (void *)GPIO_BASE, PAGE_SIZE);
|
||||||
map_periph(&dma_regs, (void *)DMA_BASE, PAGE_SIZE);
|
map_periph(&dma_regs, (void *)DMA_BASE, PAGE_SIZE);
|
||||||
map_periph(&clk_regs, (void *)CLK_BASE, PAGE_SIZE);
|
map_periph(&clk_regs, (void *)CLK_BASE, PAGE_SIZE);
|
||||||
@ -288,22 +307,29 @@ void map_devices(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Catastrophic failure in initial setup
|
// Catastrophic failure in initial setup
|
||||||
void fail(char *s)
|
void fail(char *s) {
|
||||||
{
|
|
||||||
printf(s);
|
printf(s);
|
||||||
terminate(0);
|
terminate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free memory segments and exit
|
// Free memory segments and exit
|
||||||
void terminate(int sig)
|
void terminate(int sig) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("Closing\n");
|
printf("Closing\n");
|
||||||
if (gpio_regs.virt)
|
close(udpSocket);
|
||||||
{
|
|
||||||
for (i=0; i<LED_NCHANS; i++)
|
for (size_t i = 0; i < chan_ledcount; ++i) {
|
||||||
gpio_mode(LED_D0_PIN+i, GPIO_IN);
|
rgb_txdata(off_rgbs, &tx_buffer[LED_TX_OSET(i)]);
|
||||||
|
}
|
||||||
|
swap_bytes(tx_buffer, TX_BUFF_SIZE(chan_ledcount));
|
||||||
|
memcpy(txdata, tx_buffer, TX_BUFF_SIZE(chan_ledcount));
|
||||||
|
start_smi(&vc_mem);
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
if (gpio_regs.virt) {
|
||||||
|
for (i = 0; i < LED_NCHANS; i++)
|
||||||
|
gpio_mode(LED_D0_PIN + i, GPIO_IN);
|
||||||
}
|
}
|
||||||
if (smi_regs.virt)
|
if (smi_regs.virt)
|
||||||
*REG32(smi_regs, SMI_CS) = 0;
|
*REG32(smi_regs, SMI_CS) = 0;
|
||||||
@ -317,14 +343,13 @@ void terminate(int sig)
|
|||||||
|
|
||||||
// Initialise SMI, given data width, time step, and setup/hold/strobe counts
|
// Initialise SMI, given data width, time step, and setup/hold/strobe counts
|
||||||
// Step value is in nanoseconds: even numbers, 2 to 30
|
// Step value is in nanoseconds: even numbers, 2 to 30
|
||||||
void init_smi(int width, int ns, int setup, int strobe, int hold)
|
void init_smi(int width, int ns, int setup, int strobe, int hold) {
|
||||||
{
|
|
||||||
int i, divi = ns / 2;
|
int i, divi = ns / 2;
|
||||||
|
|
||||||
smi_cs = (SMI_CS_REG *) REG32(smi_regs, SMI_CS);
|
smi_cs = (SMI_CS_REG *)REG32(smi_regs, SMI_CS);
|
||||||
smi_l = (SMI_L_REG *) REG32(smi_regs, SMI_L);
|
smi_l = (SMI_L_REG *)REG32(smi_regs, SMI_L);
|
||||||
smi_a = (SMI_A_REG *) REG32(smi_regs, SMI_A);
|
smi_a = (SMI_A_REG *)REG32(smi_regs, SMI_A);
|
||||||
smi_d = (SMI_D_REG *) REG32(smi_regs, SMI_D);
|
smi_d = (SMI_D_REG *)REG32(smi_regs, SMI_D);
|
||||||
smi_dmc = (SMI_DMC_REG *)REG32(smi_regs, SMI_DMC);
|
smi_dmc = (SMI_DMC_REG *)REG32(smi_regs, SMI_DMC);
|
||||||
smi_dsr = (SMI_DSR_REG *)REG32(smi_regs, SMI_DSR0);
|
smi_dsr = (SMI_DSR_REG *)REG32(smi_regs, SMI_DSR0);
|
||||||
smi_dsw = (SMI_DSW_REG *)REG32(smi_regs, SMI_DSW0);
|
smi_dsw = (SMI_DSW_REG *)REG32(smi_regs, SMI_DSW0);
|
||||||
@ -333,17 +358,18 @@ void init_smi(int width, int ns, int setup, int strobe, int hold)
|
|||||||
smi_dcd = (SMI_DCD_REG *)REG32(smi_regs, SMI_DCD);
|
smi_dcd = (SMI_DCD_REG *)REG32(smi_regs, SMI_DCD);
|
||||||
smi_cs->value = smi_l->value = smi_a->value = 0;
|
smi_cs->value = smi_l->value = smi_a->value = 0;
|
||||||
smi_dsr->value = smi_dsw->value = smi_dcs->value = smi_dca->value = 0;
|
smi_dsr->value = smi_dsw->value = smi_dcs->value = smi_dca->value = 0;
|
||||||
if (*REG32(clk_regs, CLK_SMI_DIV) != divi << 12)
|
if (*REG32(clk_regs, CLK_SMI_DIV) != divi << 12) {
|
||||||
{
|
|
||||||
*REG32(clk_regs, CLK_SMI_CTL) = CLK_PASSWD | (1 << 5);
|
*REG32(clk_regs, CLK_SMI_CTL) = CLK_PASSWD | (1 << 5);
|
||||||
usleep(10);
|
usleep(10);
|
||||||
while (*REG32(clk_regs, CLK_SMI_CTL) & (1 << 7)) ;
|
while (*REG32(clk_regs, CLK_SMI_CTL) & (1 << 7))
|
||||||
|
;
|
||||||
usleep(10);
|
usleep(10);
|
||||||
*REG32(clk_regs, CLK_SMI_DIV) = CLK_PASSWD | (divi << 12);
|
*REG32(clk_regs, CLK_SMI_DIV) = CLK_PASSWD | (divi << 12);
|
||||||
usleep(10);
|
usleep(10);
|
||||||
*REG32(clk_regs, CLK_SMI_CTL) = CLK_PASSWD | 6 | (1 << 4);
|
*REG32(clk_regs, CLK_SMI_CTL) = CLK_PASSWD | 6 | (1 << 4);
|
||||||
usleep(10);
|
usleep(10);
|
||||||
while ((*REG32(clk_regs, CLK_SMI_CTL) & (1 << 7)) == 0) ;
|
while ((*REG32(clk_regs, CLK_SMI_CTL) & (1 << 7)) == 0)
|
||||||
|
;
|
||||||
usleep(100);
|
usleep(100);
|
||||||
}
|
}
|
||||||
if (smi_cs->seterr)
|
if (smi_cs->seterr)
|
||||||
@ -354,16 +380,15 @@ void init_smi(int width, int ns, int setup, int strobe, int hold)
|
|||||||
smi_dmc->panicr = smi_dmc->panicw = 8;
|
smi_dmc->panicr = smi_dmc->panicw = 8;
|
||||||
smi_dmc->reqr = smi_dmc->reqw = REQUEST_THRESH;
|
smi_dmc->reqr = smi_dmc->reqw = REQUEST_THRESH;
|
||||||
smi_dsr->rwidth = smi_dsw->wwidth = width;
|
smi_dsr->rwidth = smi_dsw->wwidth = width;
|
||||||
for (i=0; i<LED_NCHANS; i++)
|
for (i = 0; i < LED_NCHANS; i++)
|
||||||
gpio_mode(LED_D0_PIN+i, GPIO_ALT1);
|
gpio_mode(LED_D0_PIN + i, GPIO_ALT1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up SMI transfers using DMA
|
// Set up SMI transfers using DMA
|
||||||
void setup_smi_dma(MEM_MAP *mp, int nsamp)
|
void setup_smi_dma(MEM_MAP *mp, int nsamp) {
|
||||||
{
|
DMA_CB *cbs = mp->virt;
|
||||||
DMA_CB *cbs=mp->virt;
|
|
||||||
|
|
||||||
txdata = (TXDATA_T *)(cbs+1);
|
txdata = (TXDATA_T *)(cbs + 1);
|
||||||
smi_dmc->dmaen = 1;
|
smi_dmc->dmaen = 1;
|
||||||
smi_cs->enable = 1;
|
smi_cs->enable = 1;
|
||||||
smi_cs->clear = 1;
|
smi_cs->clear = 1;
|
||||||
@ -378,9 +403,8 @@ void setup_smi_dma(MEM_MAP *mp, int nsamp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start SMI DMA transfers
|
// Start SMI DMA transfers
|
||||||
void start_smi(MEM_MAP *mp)
|
void start_smi(MEM_MAP *mp) {
|
||||||
{
|
DMA_CB *cbs = mp->virt;
|
||||||
DMA_CB *cbs=mp->virt;
|
|
||||||
|
|
||||||
start_dma(mp, DMA_CHAN, &cbs[0], 0);
|
start_dma(mp, DMA_CHAN, &cbs[0], 0);
|
||||||
smi_cs->start = 1;
|
smi_cs->start = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user