New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support for raspyrfm hardware #431
base: staging
Are you sure you want to change the base?
Conversation
Finally, RaspyFM 👍 Can you change the license to MPLv2? Also, you do have the posibility to make a unit test for it as well on the rewrite branch? |
Also, don't forget to include that manual page. |
Can you give me some hints how to do that? |
This is my 433gpio unittest: Which uses the DSO: |
961e27f
to
4292759
Compare
|
Here is the compile command: Also, i'm fine with a seperate hardware module folder like in the protocols, but currently all hardware modules descriptions are put in the 433.92Mhz / 868Mhz
------------------
.. include:: ../hardware/_raspyrfm.rst Also, you documentation file has some issues, this fixes it: .. |yes| image:: ../images/yes.png
.. |no| image:: ../images/no.png
.. role:: underline
:class: underline
+------------------+-------------+
| **Feature** | **Support** |
+------------------+-------------+
| Sending | |yes| |
+------------------+-------------+
| Receiving | |yes| |
+------------------+-------------+
| Config | |yes| |
+------------------+-------------+
.. rubric:: Config
Example configuration for a RaspyRFM single 868 MHz
.. code-block:: json
:linenos:
{
"hardware": {
"raspyrfm": {
"spi-channel": 0,
"frequency": 868350
}
}
}
Example configuration for a RaspyRFM single 433 MHz
.. code-block:: json
:linenos:
{
"hardware": {
"raspyrfm": {
"spi-channel": 0,
"frequency": 433920
}
}
}
.. note:: **RaspyRFM**
The RaspyRFM is a radiomodule using the RFM69 from HopeRF.
https://www.seegel-systeme.de/produkt/raspyrfm-ii/ The image path needs to be changed, when including that file in the Also, currently all hardware modules currently support both sending and receiving, and they all need to be configured to be used. So the |
Why having 2 PRs with the same content? What is the purpose of the "staging" branch, what of the "rewrite" branch? |
I understand it's confusing. You were not the first asking that question, so i will refer to the previous answer. |
Running this on the PI, nothing happens
Sorry I did not really understand how this works. How could I write a unit test for the raspyrfm? |
Don't run the bash script, check the Once you got it compiled, run You can see the output of this all here on travis:
What i did for the On this line a file socket is being created https://github.com/pilight/pilight/blob/rewrite/tests/hardware_433gpio_receive.c#L110-L117 called I use that socket here to mimic activity on Inside The only difference from real gpio is that we cannot read with So what i'm doing is just mimicing real GPIO activity as you would normally create with a scope, but now done fully software wise. |
Thank you for the detailed explaination! I see a bit clearer now. However writing a unittest for the RaspyRFM could be complex as I would have to emulate the behavior of the Chip with all the used registers. I'm afraid I can not contribute that. |
The problem is that if we don't get that unittest i can't guarentee the functionality of the RaspyRFM in future versions. As you might have noticed, i'm currently porting all modules to lua. At the moment, i'm rewriting all hardware modules to lua. If i don't have a unittest, the hardware module just won't be supported, because i have no way to test against when porting the current code to lua. Also, writing i2c unittests isn't that difficult as i2c can be emulated pretty easily. You can see an example here where i wrote one for the BMP180, LM75 and the LM76. But, the great thing about the lua modules is that i don't have give much about third party modules, because issues can be fixed super easy without having to recompiling the pilight core. |
Running the unittest for the gpio I get: `sudo LD_PRELOAD=libgpio.so ./pilight-unittest test_hardware_433gpio_receive There was 1 failure:
!!!FAILURES!!! What does this mean? |
That the test failed. But this specific test wasn't implemented well. The new lua unittest doesn't have this issue. The other tests should succeed as well. |
I tried to implement a skeleton of a unittest for the RaspyRFM but the test does not appear in the list. What did I miss? See |
Add your test like this |
Ok, I updated my branch Meanwhile my hardwaremodule's init is called but the unittest failes at this point:
Where do I have to set the platform? I could not figure it out in the 433gpio unittest. |
You should configure it first in the config: |
Meanwhile my IRQ routine in the hardwaremodule is called by the unittest.
The RaspyRfm is actually using SPI, not I2C. How can I connect "the other side" from software? |
I've build a proof-of-concept that might work: Place all files in the cmake build folder libgpio.c /*
Copyright (C) 2013 - 2016 CurlyMo
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#define __USE_GNU
#include <dlfcn.h>
#include "../libs/pilight/core/log.h"
#include "../libs/pilight/core/mem.h"
#include "../libs/libuv/uv.h"
static int state[255] = { 0 };
static uv_os_fd_t fd[255] = { -1 };
static int (* ioctl_callback)(int fd, unsigned long req, void *cmd) = NULL;
#ifdef _WIN32
__declspec(dllexport)
#endif
int wiringXSetup(char *name, void (*func)(int, char *, int, const char *, ...)) {
if(name != NULL && strcmp(name, "test") == 0) {
return -999;
}
int i = 0;
for(i=0;i<255;i++) {
fd[i] = -1;
state[i] = 0;
}
if(name == NULL || strcmp(name, "gpio-stub") == 0) {
return 0;
}
return -1;
}
int wiringXValidGPIO(int gpio) {
if(gpio == 0 || gpio == 1 || gpio == 2 || gpio == 14 || gpio == 10) {
return 0;
}
return -1;
}
int digitalWrite(int gpio, int mode) {
return ((send(fd[gpio], "a", 1, 0) == 1) ? 0 : -1);
}
char *wiringXPlatform(void) {
return "gpio-stub";
}
int digitalRead(int gpio) {
state[gpio] ^= 1;
return state[gpio];
}
int wiringXSelectableFd(int gpio) {
return fd[gpio];
}
int pinMode(int gpio, int mode) {
struct sockaddr_un address;
if(fd[gpio] == -1) {
if((fd[gpio] = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
logprintf(LOG_ERR, "socket");
return -1;
}
/* start with a clean address structure */
memset(&address, 0, sizeof(struct sockaddr_un));
address.sun_family = AF_UNIX;
snprintf(address.sun_path, 128, "/dev/gpio%d", gpio);
if(connect(fd[gpio], (struct sockaddr *)&address, sizeof(struct sockaddr_un)) != 0) {
logprintf(LOG_ERR, "connect");
return -1;
}
}
return 0;
}
void wiringXIOCTLCallback(int (*callback)(int fd, unsigned long req, void *cmd)) {
ioctl_callback = callback;
}
int ioctl(int fd, unsigned long req, void *cmd) {
if(ioctl_callback != NULL) {
return ioctl_callback(fd, req, cmd);
} else {
return -1;
}
}
int wiringXGC(void) {
int *(*real)(void) = dlsym(RTLD_NEXT, "wiringXGC");
if(NULL == real) {
fprintf(stderr, "dlsym");
}
real();
int i = 0;
for(i=0;i<255;i++) {
if(fd[i] > 0) {
close(fd[i]);
}
}
return 0;
}
int wiringXISR(int gpio, int mode) {
if(gpio == 2) {
return -1;
}
if(fd[gpio] == -1) {
return pinMode(gpio, mode);
} else {
return 0;
}
} test.c #include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <wiringx.h>
#include <sys/ioctl.h>
#ifndef __FreeBSD__
#include <linux/spi/spidev.h>
#endif
#include "libuv/uv.h"
#define BUFFER_SIZE 1024
void wiringXIOCTLCallback(int (*callback)(int fd, unsigned long req, void *cmd));
int ioctl_callback(int fd, unsigned long req, void *cmd) {
printf("%d %lu\n", fd, req);
return 0;
}
static void close_cb(uv_handle_t *handle) {
free(handle);
}
static void walk_cb(uv_handle_t *handle, void *arg) {
if(!uv_is_closing(handle)) {
uv_close(handle, close_cb);
}
}
void open_cb(uv_fs_t *req) {
wiringXIOCTLCallback(ioctl_callback);
wiringXSPISetup(0, 2500000UL);
}
int main(void) {
uv_fs_t *req = malloc(sizeof(uv_fs_t));
uv_fs_open(uv_default_loop(), req, "/dev/spidev0.0", O_CREAT, O_RDWR, open_cb);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_walk(uv_default_loop(), walk_cb, NULL);
uv_run(uv_default_loop(), UV_RUN_ONCE);
while(uv_loop_close(uv_default_loop()) == UV_EBUSY) {
uv_run(uv_default_loop(), UV_RUN_ONCE);
}
return 1;
} Makefile # inside the cmake build folder.
gcc -c -Wall -Werror -fpic libgpio.c -I../libs
gcc -shared -o libgpio.so libgpio.o
gcc -o test test.c ./libpilight.so ./libgpio.so -I../libs -lwiringx; LD_PRELOAD=./libgpio.so ./test What it does:
Can you continue with this snippet? |
Thank you very much for the snipped! I'll give it a try! Later this extension will be included in the current libgpio?
|
Ofc |
I force-pushed here: |
If you aren't using |
I just transfered basically from hardware_433gpio_receive.c, but it seems to work w/o FREE? I added a FREE to the end of my code (forced push again). The Warning disappeared but I still get the double free issue. |
Also, i couldn't confirm the double free issue. |
You did run my commit? On arm? Did you get a "TRAIN MATCH!" output?
This means I should not use xfree? |
I did and i got it.
You should, because it checks your memory allocations for you. It prevents you having to use valgrind all the time. |
I rebased my rewrite branch today to your current one. I made some adjustments to make it compile. After running I get a seg fault at
Did you change something in the deep? My latest code is again on my rewrite branch: |
No, didn't change anything there. What does |
For some reason gdb does not Work in my Crosssetup. Is there any other way to findout more? |
valgrind? |
For some reason gdb does not Work in my Crosssetup. Is there any other way to findout more? |
I managed to run GDB directly on the PI in a terminal. When running pilight-unittest with test_hardware_raspyrfm_receive I get
|
I have to dig into this. |
It was indeed due to some serieus changes i did porting the hardware modules to lua. I would advice you to stay on 2ffea92 for now. |
I rebased my feature on your suggested commit. Somewhing weired is going on now. When running the pilight-daemon, execution stucks in the while loop (100% CPU) here: https://github.com/Phunkafizer/pilight/blob/1e7667152fd4cfaf7a1cedc0230998731e086813/daemon.c#L1619 This call always returns 0, because options.c says
Am I missing something? |
The daemon doesn't work. Only |
I don't get it really. I use the same way as in hardware_433gpio_receive.c: MALLOC for the client_req, and xfree at the end. I'm getting:
Unfreed and double free at the same time? |
As i said before, you need to use |
I'm doing so:
Sorry was on the wrong branch, working now! I'll go on with the unittest! |
After understanding uvlib better unittest is work for send & receive now. Thank you very much for your help. |
You're welcome. Now these unittests work, we can work towards porting the whole thing into a Lua module 😄 I will do the initial work based on your unittest, when i'm done, you can test the whole thing with the real hardware. |
70e8707
to
635ce49
Compare
Yes, time has passed quickly! I tried all available unittests for the lua raspyrfm, they all have the same result:
|
They all run fine here:
Did you compile it properly?
|
I started from scratch again (branch raspyrfm). When compiling I get
|
There must be something wrong with your dev machien because What's the environment you are working in? Raspberry Pi or cross-compilation? |
After running cmake again it worked fine, but getting the same unittestresults as before... |
Which one, because the performance difference between versions is quite big. |
It's the Raspberry 3B. I'll try with a second PI and a fresh SD card. |
Add support for the RaspyRFM 434/868 module: https://www.seegel-systeme.de/produkt/raspyrfm-ii/