Permalink
Browse files

[channelout] Initial work for Komby nRF output from the Pi

Note: there may be bugs and TODOs left, but pretty much ready to go.
Tested both direct file playback and bridge mode, but I have not done
any timing tests on how long it takes to write to SPI, nor checked
maximum channel outputs.
  • Loading branch information...
Materdaddy committed Oct 6, 2014
1 parent 3b87e6a commit 02588f73fdf059b72f3334e0aa3afe57fcbf3a93
Showing with 428 additions and 3 deletions.
  1. +1 −0 scripts/common
  2. +20 −2 src/Makefile
  3. +279 −0 src/channeloutput/SPInRF24L01.c
  4. +34 −0 src/channeloutput/SPInRF24L01.h
  5. +3 −0 src/channeloutput/channeloutput.c
  6. +91 −1 www/channeloutputs.php
View
@@ -19,6 +19,7 @@ then
PATHDIRS="${FPPDIR}/scripts/:${FPPDIR}/src/"
fi
export PATH=${PATHDIRS}:${PATH}
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${FPPDIR}/external/RF24
PLATFORM=$(cat /etc/fpp/platform 2> /dev/null)
SUDO=${SUDO:-sudo}
View
@@ -28,6 +28,7 @@ OBJECTS_fppd = \
channeloutput/E131.o \
channeloutput/FPD.o \
channeloutput/serialutil.o \
channeloutput/SPInRF24L01.o \
channeloutput/SPIws2801.o \
channeloutput/Triks-C.o \
channeloutput/USBDMXOpen.o \
@@ -93,9 +94,19 @@ ifeq '$(ARCH)' 'Raspberry Pi'
# do something RaspPi-y
CFLAGS += \
-DUSEWIRINGPI \
-DUSENRF \
-I../external/RF24/ \
$(NULL)
LIBS_fppd += \
-lwiringPi -lwiringPiDev \
-lwiringPi \
-lwiringPiDev \
-lrf24-bcm \
$(NULL)
LDFLAGS_fppd += \
-L../external/RF24 \
$(NULL)
DEPS_fppd += \
../external/RF24/librf24-bcm.so \
$(NULL)
else
# do something Linux-y
@@ -123,11 +134,18 @@ fpp: $(OBJECTS_fpp)
fppmm: $(OBJECTS_fppmm)
$(CCACHE) $(CC) $(CFLAGS_$@) $(OBJECTS_$@) $(LIBS_$@) $(LDFLAGS_$@) -o $@
fppd: $(OBJECTS_fppd)
fppd: $(OBJECTS_fppd) $(DEPS_fppd)
$(CCACHE) $(CC) $(CFLAGS_$@) $(OBJECTS_$@) $(LIBS_$@) $(LDFLAGS_$@) -o $@
%.o: %.c %.h Makefile
$(CCACHE) $(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJECTS_fpp) $(OBJECTS_fppmm) $(OBJECTS_fppd) fpp fppmm fppd
make -C ../external/RF24 clean
../external/RF24/librf24-bcm.so:
@echo "Building RF24 library"
@make -C ../external/RF24/
@ln -s librf24-bcm.so.1.0 ../external/RF24/librf24-bcm.so.1
@ln -s librf24-bcm.so.1 ../external/RF24/librf24-bcm.so
@@ -0,0 +1,279 @@
/*
* nRF24L01 SPI handler for Falcon Pi Player (FPP)
*
* Copyright (C) 2013 the Falcon Pi Player Developers
* Initial development by:
* - David Pitts (dpitts)
* - Tony Mace (MyKroFt)
* - Mathew Mrosko (Materdaddy)
* - Chris Pinkham (CaptainMurdoch)
* For additional credits and developers, see credits.php.
*
* The Falcon Pi Player (FPP) is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "log.h"
#include "settings.h"
#include "SPInRF24L01.h"
#ifdef USENRF
# include "RF24.h"
#else
//TODO: Stub for non-pi builds!
# error "TODO: Stub for non-Pi"
#endif
//TODO: Check max channels
#define SPINRF24L01_MAX_CHANNELS 512
const uint64_t pipes[2] = {
0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL
};
/////////////////////////////////////////////////////////////////////////////
typedef struct spiNRF24L01PrivData {
RF24 *radio;
rf24_datarate_e speed;
int channel;
} SPInRF24L01PrivData;
/////////////////////////////////////////////////////////////////////////////
/*
*
*/
void SPInRF24L01_Dump(SPInRF24L01PrivData *privData) {
LogDebug(VB_CHANNELOUT, " privData: %p\n", privData);
if (!privData)
return;
if ( privData->speed == RF24_1MBPS )
LogDebug(VB_CHANNELOUT, " speed : 1MBPS\n");
else if ( privData->speed == RF24_250KBPS )
LogDebug(VB_CHANNELOUT, " speed : 250KBPS\n");
LogDebug(VB_CHANNELOUT, " channel : %d\n", privData->channel);
}
/*
*
*/
int SPInRF24L01_Open(char *configStr, void **privDataPtr) {
//TODO: Add help to the channeloutput page in UI
LogDebug(VB_CHANNELOUT, "SPInRF24L01_Open('%s')\n", configStr);
SPInRF24L01PrivData *privData =
(SPInRF24L01PrivData *)malloc(sizeof(SPInRF24L01PrivData));
bzero(privData, sizeof(SPInRF24L01PrivData));
char speed[2] = {0};
char channel[4] = {0};
char *s = strtok(configStr, ";");
while (s) {
char tmp[128];
char *div = NULL;
strcpy(tmp, s);
div = strchr(tmp, '=');
if (div) {
*div = '\0';
div++;
if (!strcmp(tmp, "speed")) {
LogDebug(VB_CHANNELOUT, "Using %s for nRF speed\n", div);
strcpy(speed, div);
}
else if (!strcmp(tmp, "channel")) {
LogDebug(VB_CHANNELOUT, "Using %s for nRF channel\n", div);
strcpy(channel, div);
}
}
s = strtok(NULL, ";");
}
if (!strcmp(speed, "0"))
{
privData->speed = RF24_250KBPS;
}
else if (!strcmp(speed, "1"))
{
privData->speed = RF24_1MBPS;
}
else
{
LogErr(VB_CHANNELOUT, "Invalid speed '%s' parsed from config string: %s\n",
speed, configStr);
free(privData);
return 0;
}
privData->channel = atoi(channel);
//TODO: Warn if in the "FCC rectricted frequency range"
if (privData->channel <= 0 || privData->channel > 125)
{
LogErr(VB_CHANNELOUT, "Invalid channel '%d' parsed from config string: %s\n",
channel, configStr);
free(privData);
return 0;
}
//TODO: Support other pins/speeds on other SPI bus?
RF24 *radio = new RF24(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
if (!radio)
{
LogErr(VB_CHANNELOUT, "Failed to create our radio instance, unable to continue!\n");
free(privData);
return 0;
}
// This section of code was basically lifted from the initialization in
// Komby's RF1 library. This was tested on a Pi using a similar version
// of the RF24 library and works, so no further investigation to whether
// or not all of these are required was done.
radio->begin();
radio->setDataRate(privData->speed);
radio->setRetries(0,0);
radio->setPayloadSize(32);
radio->setAutoAck(0);
radio->setChannel(privData->channel);
radio->setCRCLength(RF24_CRC_16);
radio->openWritingPipe(pipes[0]);
radio->openReadingPipe(1,pipes[1]);
radio->setPALevel(RF24_PA_MAX);
radio->flush_tx();
radio->powerUp();
privData->radio = radio;
SPInRF24L01_Dump(privData);
if (logMask & VB_CHANNELOUT && logLevel & LOG_DEBUG) {
privData->radio->printDetails();
}
*privDataPtr = privData;
return 1;
}
/*
*
*/
int SPInRF24L01_Close(void *data) {
LogDebug(VB_CHANNELOUT, "SPInRF24L01_Close(%p)\n", data);
SPInRF24L01PrivData *privData = (SPInRF24L01PrivData*)data;
SPInRF24L01_Dump(privData);
delete(privData->radio);
privData->radio = NULL;
}
/*
*
*/
int SPInRF24L01_IsConfigured(void) {
// FIXME, needs work once new UI is figured out
// if ((strcmp(getUSBDonglePort(),"DISABLED")) &&
// (!strcmp(getUSBDongleType(), "Pixelnet")))
// return 1;
return 0;
}
/*
*
*/
int SPInRF24L01_IsActive(void *data) {
LogDebug(VB_CHANNELOUT, "SPInRF24L01_IsActive(%p)\n", data);
SPInRF24L01PrivData *privData = (SPInRF24L01PrivData*)data;
if (!privData)
return 0;
SPInRF24L01_Dump(privData);
return 0;
}
/*
*
*/
int SPInRF24L01_SendData(void *data, char *channelData, int channelCount)
{
LogDebug(VB_CHANNELDATA, "SPInRF24L01_SendData(%p, %p, %d)\n",
data, channelData, channelCount);
char packet[32];
int i = 0;
SPInRF24L01PrivData *privData = (SPInRF24L01PrivData*)data;
RF24 *radio = privData->radio;
if (channelCount > SPINRF24L01_MAX_CHANNELS) {
LogErr(VB_CHANNELOUT,
"SPInRF24L01_SendData() tried to send %d bytes when max is %d\n",
channelCount, SPINRF24L01_MAX_CHANNELS);
return 0;
}
for (i = 0; i*30 < channelCount; i++)
{
LogDebug(VB_CHANNELOUT,
"Shipping off packet %d (offset: %d/%d, size: %d)\n",
i, i*30, channelCount,
((i*30)+30 > channelCount ? channelCount - i*30 : 30));
bzero(packet, sizeof(packet));
memcpy(packet, channelData+(i*30), ((i*30)+30 > channelCount ? channelCount - i*30 : 30));
packet[30] = i;
radio->write(packet,32);
}
}
/*
* *
* */
int SPInRF24L01_MaxChannels(void *data)
{
return SPINRF24L01_MAX_CHANNELS;
}
/*
* Declare our external interface struct
*/
FPPChannelOutput SPInRF24L01Output = {
.maxChannels = SPInRF24L01_MaxChannels,
.open = SPInRF24L01_Open,
.close = SPInRF24L01_Close,
.isConfigured = SPInRF24L01_IsConfigured,
.isActive = SPInRF24L01_IsActive,
.send = SPInRF24L01_SendData
};
@@ -0,0 +1,34 @@
/*
* WS2801 SPI handler for Falcon Pi Player (FPP)
*
* Copyright (C) 2013 the Falcon Pi Player Developers
* Initial development by:
* - David Pitts (dpitts)
* - Tony Mace (MyKroFt)
* - Mathew Mrosko (Materdaddy)
* - Chris Pinkham (CaptainMurdoch)
* For additional credits and developers, see credits.php.
*
* The Falcon Pi Player (FPP) is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SPINRF24L01_H
#define _SPINRF24L01_H
#include "channeloutput.h"
/* Expose our interface */
extern FPPChannelOutput SPInRF24L01Output;
#endif
@@ -36,6 +36,7 @@
#include "sequence.h"
#include "settings.h"
#include "SPIws2801.h"
#include "SPInRF24L01.h"
#include "USBDMXOpen.h"
#include "USBDMXPro.h"
#include "USBPixelnet.h"
@@ -187,6 +188,8 @@ int InitializeChannelOutputs(void) {
channelOutputs[i].output = &USBRenardOutput;
} else if (!strcmp(type, "SPI-WS2801")) {
channelOutputs[i].output = &SPIws2801Output;
} else if (!strcmp(type, "SPI-nRF24L01")) {
channelOutputs[i].output = &SPInRF24L01Output;
} else if (!strcmp(type, "Triks-C")) {
channelOutputs[i].output = &TriksCOutput;
} else {
Oops, something went wrong.

0 comments on commit 02588f7

Please sign in to comment.