优化433MHZ中继转发
This commit is contained in:
16
433MHZ/rc-switch-pico/.gitignore
vendored
Normal file
16
433MHZ/rc-switch-pico/.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
.DS_Store
|
||||
CMakeFiles/
|
||||
elf2uf2/
|
||||
generated/
|
||||
pico-sdk/
|
||||
CMakeCache.txt
|
||||
CMakeDoxyfile.in
|
||||
CMakeDoxygenDefaults.cmake
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
*.bin
|
||||
*.dis
|
||||
*.elf
|
||||
*.elf.map
|
||||
*.hex
|
||||
*.uf2
|
23
433MHZ/rc-switch-pico/CMakeLists.txt
Normal file
23
433MHZ/rc-switch-pico/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
# Pull in SDK (must be before project)
|
||||
include(pico_sdk_import.cmake)
|
||||
|
||||
project(pico_examples C CXX ASM)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})
|
||||
|
||||
# Initialize the SDK
|
||||
pico_sdk_init()
|
||||
|
||||
# Add blink example
|
||||
add_subdirectory(examples/Transmit)
|
||||
add_subdirectory(examples/Receive)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
21
433MHZ/rc-switch-pico/LICENSE
Normal file
21
433MHZ/rc-switch-pico/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 oshawa-connection
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
31
433MHZ/rc-switch-pico/examples/Forward/CMakeLists.txt
Normal file
31
433MHZ/rc-switch-pico/examples/Forward/CMakeLists.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
add_executable(forward
|
||||
Forward.cc
|
||||
../../radio-switch.cc
|
||||
)
|
||||
|
||||
|
||||
add_compile_options(-Wall
|
||||
-Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
|
||||
-Wno-unused-function # we have some for the docs that aren't called
|
||||
-Wno-maybe-uninitialized
|
||||
)
|
||||
|
||||
# Pull in our pico_stdlib which pulls in commonly used features
|
||||
|
||||
target_link_libraries(forward
|
||||
pico_stdlib
|
||||
hardware_adc
|
||||
pico_multicore)
|
||||
|
||||
# enable usb output, disable uart output
|
||||
pico_enable_stdio_usb(forward 1)
|
||||
pico_enable_stdio_uart(forward 0)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(forward)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
219
433MHZ/rc-switch-pico/examples/Forward/Forward.cc
Normal file
219
433MHZ/rc-switch-pico/examples/Forward/Forward.cc
Normal file
@@ -0,0 +1,219 @@
|
||||
#include <iostream>
|
||||
#include "pico/stdlib.h"
|
||||
#include "../../radio-switch.h"
|
||||
#include "pico/stdio.h"
|
||||
#include "pico/multicore.h"
|
||||
#include <map> // map
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define BUFFER_SIZ 270
|
||||
|
||||
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
||||
const uint RADIO_TRANSMIT_PIN = 16; // 433发射模块引脚
|
||||
const uint RADIO_RECEIVER_PIN = 17; // 433接收模块引脚
|
||||
const uint PASSWD_LEN = 3; // 随机数几位
|
||||
const uint QUEUES_NUM = 3; // 队列数量, 满了发送
|
||||
const uint QUEUES_WAIT = 60; // 队列等待时间, 单位秒, 队列未满时
|
||||
|
||||
char ins[] = "55";
|
||||
char outs = '1';
|
||||
|
||||
|
||||
// 闪烁LED
|
||||
static void light()
|
||||
{
|
||||
gpio_init(LED_PIN);
|
||||
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||||
gpio_put(LED_PIN, 1);
|
||||
sleep_ms(100);
|
||||
gpio_put(LED_PIN, 0);
|
||||
sleep_ms(100);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
static const char pool[] = {
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||
};
|
||||
|
||||
// 随即数
|
||||
static int RAND()
|
||||
{
|
||||
char password[BUFFER_SIZ];
|
||||
int i = 0;
|
||||
FILE *fp;
|
||||
|
||||
memset(password, 0, BUFFER_SIZ);
|
||||
srand(time(NULL));
|
||||
|
||||
while (i != PASSWD_LEN) {
|
||||
password[i++] = pool[rand() % sizeof(pool)];
|
||||
}
|
||||
|
||||
//printf("%d\n", atoi(password));
|
||||
return atoi(password);
|
||||
}
|
||||
|
||||
static void SEND(const int ID)
|
||||
{
|
||||
int RANDOM = 500;
|
||||
const int LOOP_NUM = 1; // 循环发送次数
|
||||
const uint PULSE_LENGTH = 169; // set this to PULSELENGTH RECIEVED
|
||||
const uint REPEAT_TRANSMIT = 5; // set this to whatever works best for you. // 重复发送
|
||||
const uint PROTOCOL = 1; // set this to PROTOCOL RECIEVED
|
||||
const uint BIT_LENGTH = 24; // set this to BIT LENGTH RECIEVED
|
||||
|
||||
gpio_init(RADIO_TRANSMIT_PIN);
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
mySwitch.enableTransmit(RADIO_TRANSMIT_PIN);
|
||||
mySwitch.setProtocol(PROTOCOL);
|
||||
mySwitch.setPulseLength(PULSE_LENGTH);
|
||||
mySwitch.setRepeatTransmit(REPEAT_TRANSMIT);
|
||||
|
||||
|
||||
for (int i = 0; i <= LOOP_NUM; i++) {
|
||||
RANDOM = RAND();
|
||||
light(); // 灯闪烁
|
||||
|
||||
sleep_ms(RANDOM * 2 / 3); // 等待随机时间
|
||||
|
||||
mySwitch.send(ID, BIT_LENGTH); // 发射
|
||||
sleep_ms(100);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
static int int_string(int val, char *inchars, int SIZE, int *inchars_len, char *outchars, int *outchars_len)
|
||||
{
|
||||
memset(inchars, 0, SIZE);
|
||||
memset(outchars, 0, SIZE);
|
||||
|
||||
|
||||
snprintf(inchars, SIZE, "%d", val);
|
||||
*inchars_len = strlen(inchars);
|
||||
|
||||
if (0 == strncasecmp(inchars, ins, 2)) {
|
||||
outchars[0] = outs;
|
||||
outchars[1] = outs;
|
||||
strncpy(outchars + 2, inchars + 2, (*inchars_len) - 2);
|
||||
|
||||
*outchars_len = strlen(outchars);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 核心0发送数据到核心1, 核心1判断是否有数据到来, 然后打印.
|
||||
static void core1_main()
|
||||
{
|
||||
gpio_init(RADIO_RECEIVER_PIN);
|
||||
|
||||
RCSwitch rcSwitch = RCSwitch();
|
||||
rcSwitch.enableReceive(RADIO_RECEIVER_PIN);
|
||||
|
||||
char inchars[BUFFER_SIZ];
|
||||
char outchars[BUFFER_SIZ];
|
||||
int inchars_len;
|
||||
int outchars_len;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (rcSwitch.available())
|
||||
{
|
||||
light(); // 灯闪烁
|
||||
|
||||
uint32_t val = rcSwitch.getReceivedValue();
|
||||
|
||||
int_string(val, inchars, BUFFER_SIZ, &inchars_len, outchars, &outchars_len);
|
||||
|
||||
if (val != 0)
|
||||
{
|
||||
if (inchars[0] == ins[0] && inchars[1] == ins[1])
|
||||
{
|
||||
multicore_fifo_push_blocking(atoi(outchars));
|
||||
}
|
||||
else
|
||||
{
|
||||
rcSwitch.resetAvailable();
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
rcSwitch.resetAvailable();
|
||||
val = 0;
|
||||
}
|
||||
|
||||
|
||||
sleep_ms(100);
|
||||
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
stdio_init_all();
|
||||
|
||||
std::map < int, int >idcode;
|
||||
int count=0;
|
||||
uint32_t i=0;
|
||||
|
||||
|
||||
multicore_reset_core1();
|
||||
multicore_launch_core1(core1_main);
|
||||
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (multicore_fifo_rvalid())
|
||||
{
|
||||
i = multicore_fifo_pop_blocking(); // 读取核心1发送来的数据
|
||||
|
||||
idcode.insert( { // 插入map
|
||||
i, i}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (idcode.size() >= QUEUES_NUM) // 等于3个时发送
|
||||
{
|
||||
for (auto it: idcode)
|
||||
{
|
||||
|
||||
printf("核心0转发433MHZ %u\n", it.first);
|
||||
SEND(it.first);
|
||||
}
|
||||
|
||||
idcode.clear();
|
||||
}
|
||||
else // 一直没有3个时候, 过一段时间发送
|
||||
{
|
||||
count++; // 计数
|
||||
|
||||
if (count == QUEUES_WAIT*10) // 秒
|
||||
{
|
||||
for (auto it: idcode)
|
||||
{
|
||||
printf("核心0转发433MHZ %u\n", it.first);
|
||||
SEND(it.first);
|
||||
}
|
||||
|
||||
idcode.clear();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sleep_ms(10);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
31
433MHZ/rc-switch-pico/examples/Receive/CMakeLists.txt
Normal file
31
433MHZ/rc-switch-pico/examples/Receive/CMakeLists.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
add_executable(receive
|
||||
Receive.cc
|
||||
../../radio-switch.cc
|
||||
)
|
||||
|
||||
|
||||
add_compile_options(-Wall
|
||||
-Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
|
||||
-Wno-unused-function # we have some for the docs that aren't called
|
||||
-Wno-maybe-uninitialized
|
||||
)
|
||||
|
||||
# Pull in our pico_stdlib which pulls in commonly used features
|
||||
|
||||
target_link_libraries(receive
|
||||
pico_stdlib
|
||||
hardware_adc
|
||||
pico_multicore)
|
||||
|
||||
# enable usb output, disable uart output
|
||||
pico_enable_stdio_usb(receive 1)
|
||||
pico_enable_stdio_uart(receive 0)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(receive)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
156
433MHZ/rc-switch-pico/examples/Receive/Receive.cc
Normal file
156
433MHZ/rc-switch-pico/examples/Receive/Receive.cc
Normal file
@@ -0,0 +1,156 @@
|
||||
#include <iostream>
|
||||
#include "pico/stdlib.h"
|
||||
#include "../../radio-switch.h"
|
||||
#include "pico/stdio.h"
|
||||
#include "pico/multicore.h"
|
||||
#include <map> // map
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define BUFFER_SIZ 1024
|
||||
|
||||
|
||||
//const uint RADIO_TRANSMIT_PIN = 16; // 433发射模块引脚
|
||||
const uint RADIO_RECEIVER_PIN = 17; // 433接收模块引脚
|
||||
|
||||
|
||||
// 闪烁LED
|
||||
void light()
|
||||
{
|
||||
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
||||
gpio_init(LED_PIN);
|
||||
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||||
gpio_put(LED_PIN, 1);
|
||||
sleep_ms(100);
|
||||
gpio_put(LED_PIN, 0);
|
||||
sleep_ms(100);
|
||||
|
||||
}
|
||||
|
||||
int int_string(int val, char *string, int string_len, int *str_len, char *dest, int *dest_len)
|
||||
{
|
||||
memset(string, 0, string_len);
|
||||
memset(dest, 0, string_len);
|
||||
|
||||
char s[] = "55";
|
||||
char d = '1';
|
||||
|
||||
snprintf(string, string_len, "%d", val);
|
||||
*str_len = strlen(string);
|
||||
|
||||
if (0 == strncasecmp(string, s, 2)) {
|
||||
dest[0] = d;
|
||||
dest[1] = d;
|
||||
strncpy(dest + 2, string + 2, (*str_len) - 2);
|
||||
|
||||
*dest_len = strlen(dest);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 核心0发送数据到核心1, 核心1判断是否有数据到来, 然后打印.
|
||||
void core1_main()
|
||||
{
|
||||
|
||||
gpio_init(RADIO_RECEIVER_PIN);
|
||||
|
||||
RCSwitch rcSwitch = RCSwitch();
|
||||
rcSwitch.enableReceive(RADIO_RECEIVER_PIN);
|
||||
|
||||
const char s = '1';
|
||||
uint32_t val = 0;
|
||||
int str_len;
|
||||
int dest_len;
|
||||
char str[270];
|
||||
char dest[270];
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (rcSwitch.available())
|
||||
{
|
||||
light();
|
||||
|
||||
val = rcSwitch.getReceivedValue();
|
||||
|
||||
int_string(val, str, 270, &str_len, dest, &dest_len);
|
||||
|
||||
|
||||
if (val != 0) {
|
||||
if (str[0] == s && str[1] == s) {
|
||||
|
||||
multicore_fifo_push_blocking(atoi(dest));
|
||||
} else {
|
||||
rcSwitch.resetAvailable();
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
rcSwitch.resetAvailable();
|
||||
val = 0;
|
||||
}
|
||||
|
||||
|
||||
sleep_ms(130);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
stdio_init_all();
|
||||
|
||||
std::map < int, int >idcode;
|
||||
int count=0;
|
||||
uint32_t i=0;
|
||||
|
||||
|
||||
multicore_reset_core1();
|
||||
multicore_launch_core1(core1_main);
|
||||
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (multicore_fifo_rvalid()) {
|
||||
i = multicore_fifo_pop_blocking(); // 读取核心1发送来的数据
|
||||
|
||||
idcode.insert( { // 插入map
|
||||
i, i}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if (idcode.size() >= 3) { // 等于3个时发送
|
||||
for (auto it: idcode) {
|
||||
printf("核心0接收433MHZ %u\n", it.first);
|
||||
}
|
||||
|
||||
idcode.clear();
|
||||
}
|
||||
else // 一直没有3个时候, 过一段时间发送
|
||||
{
|
||||
count++; // 计数
|
||||
|
||||
if (count == 600) // 60秒
|
||||
{
|
||||
for (auto it: idcode) {
|
||||
printf("核心0接收433MHZ %u\n", it.first);
|
||||
}
|
||||
|
||||
idcode.clear();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sleep_ms(100);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
26
433MHZ/rc-switch-pico/examples/Transmit/CMakeLists.txt
Normal file
26
433MHZ/rc-switch-pico/examples/Transmit/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
add_executable(transmit
|
||||
Transmit.cc
|
||||
../../radio-switch.cc
|
||||
)
|
||||
|
||||
|
||||
add_compile_options(-Wall
|
||||
-Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
|
||||
-Wno-unused-function # we have some for the docs that aren't called
|
||||
-Wno-maybe-uninitialized
|
||||
)
|
||||
|
||||
# Pull in our pico_stdlib which pulls in commonly used features
|
||||
target_link_libraries(transmit pico_stdlib)
|
||||
|
||||
|
||||
|
||||
# enable usb output, disable uart output
|
||||
pico_enable_stdio_usb(transmit 1)
|
||||
pico_enable_stdio_uart(transmit 0)
|
||||
|
||||
|
||||
pico_enable_stdio_uart(transmit ENABLED)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(transmit)
|
94
433MHZ/rc-switch-pico/examples/Transmit/Transmit.cc
Normal file
94
433MHZ/rc-switch-pico/examples/Transmit/Transmit.cc
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <iostream>
|
||||
#include "pico/stdlib.h"
|
||||
#include "../../radio-switch.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define BUFFER_SIZ 1024
|
||||
|
||||
// 闪烁LED
|
||||
static void light()
|
||||
{
|
||||
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
||||
gpio_init(LED_PIN);
|
||||
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||||
gpio_put(LED_PIN, 1);
|
||||
sleep_ms(100);
|
||||
gpio_put(LED_PIN, 0);
|
||||
sleep_ms(100);
|
||||
|
||||
}
|
||||
|
||||
static char pool[] = {
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||
};
|
||||
|
||||
// 随即数
|
||||
static int RAND()
|
||||
{
|
||||
int PASSWD_LEN = 3;
|
||||
char password[BUFFER_SIZ];
|
||||
int i = 0;
|
||||
FILE *fp;
|
||||
|
||||
memset(password, 0, BUFFER_SIZ);
|
||||
srand(time(NULL));
|
||||
|
||||
while (i != PASSWD_LEN) {
|
||||
password[i++] = pool[rand() % sizeof(pool)];
|
||||
}
|
||||
|
||||
//printf("%d\n", atoi(password));
|
||||
|
||||
return atoi(password);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
const uint RADIO_TRANSMIT_PIN = 16; // 433发射模块引脚
|
||||
const uint BUTTON = 17; // 按钮发射
|
||||
|
||||
const uint PULSE_LENGTH = 169; // set this to PULSELENGTH RECIEVED
|
||||
const uint REPEAT_TRANSMIT = 4; // set this to whatever works best for you. // 重复发送
|
||||
const uint PROTOCOL = 1; // set this to PROTOCOL RECIEVED
|
||||
const uint BIT_LENGTH = 24; // set this to BIT LENGTH RECIEVED
|
||||
|
||||
stdio_init_all();
|
||||
gpio_init(RADIO_TRANSMIT_PIN);
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
mySwitch.enableTransmit(RADIO_TRANSMIT_PIN);
|
||||
mySwitch.setProtocol(PROTOCOL);
|
||||
mySwitch.setPulseLength(PULSE_LENGTH);
|
||||
mySwitch.setRepeatTransmit(REPEAT_TRANSMIT);
|
||||
|
||||
int RANDOM = 30;
|
||||
int LOOP_NUM = 1; // 循环发送次数
|
||||
|
||||
const int but = 55001;
|
||||
|
||||
stdio_uart_init_full(uart0, 115200, 6, 7);
|
||||
|
||||
while (1) {
|
||||
//fprintf(uart0_handle, "Hello from uart0!\r\n");
|
||||
|
||||
//if (1 == gpio_get(BUTTON)) { // 按钮按下
|
||||
for (int i = 0; i <= LOOP_NUM; i++) {
|
||||
RANDOM = RAND();
|
||||
light(); // 灯闪烁
|
||||
|
||||
sleep_ms(RANDOM * 2 / 3); // 等待随机时间
|
||||
|
||||
mySwitch.send(but, BIT_LENGTH); // 第一次发射
|
||||
sleep_ms(130);
|
||||
|
||||
//mySwitch.send(but+1, BIT_LENGTH); // 第二次发射
|
||||
//sleep_ms(130);
|
||||
}
|
||||
//}
|
||||
|
||||
sleep_ms(3000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
62
433MHZ/rc-switch-pico/pico_sdk_import.cmake
Normal file
62
433MHZ/rc-switch-pico/pico_sdk_import.cmake
Normal file
@@ -0,0 +1,62 @@
|
||||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
)
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
FetchContent_Populate(pico_sdk)
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
BIN
433MHZ/rc-switch-pico/pioasm/pioasm
Normal file
BIN
433MHZ/rc-switch-pico/pioasm/pioasm
Normal file
Binary file not shown.
728
433MHZ/rc-switch-pico/radio-switch.cc
Normal file
728
433MHZ/rc-switch-pico/radio-switch.cc
Normal file
@@ -0,0 +1,728 @@
|
||||
/*
|
||||
RCSwitch - Arduino libary for remote control outlet switches
|
||||
Copyright (c) 2011 Suat Özgür. All right reserved.
|
||||
|
||||
Contributors:
|
||||
- Andre Koehler / info(at)tomate-online(dot)de
|
||||
- Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
|
||||
- Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
|
||||
- Dominik Fischer / dom_fischer(at)web(dot)de
|
||||
- Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
|
||||
- Andreas Steinel / A.<lastname>(at)gmail(dot)com
|
||||
- Max Horn / max(at)quendi(dot)de
|
||||
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
|
||||
- Johann Richard / <first name>.<last name>(at)gmail(dot)com
|
||||
- Vlad Gheorghe / <first name>.<last name>(at)gmail(dot)com https://github.com/vgheo
|
||||
- Matias Cuenca-Acuna
|
||||
|
||||
Project home: https://github.com/sui77/rc-switch/
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "radio-switch.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/uart.h"
|
||||
|
||||
#ifdef _PICO_STDLIB_H
|
||||
#define HIGH 1
|
||||
#define LOW 0
|
||||
#endif
|
||||
|
||||
|
||||
#define PROGMEM
|
||||
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
|
||||
|
||||
|
||||
#if defined(ESP8266)
|
||||
// interrupt handler and related code must be in RAM on ESP8266,
|
||||
// according to issue #46.
|
||||
#define RECEIVE_ATTR ICACHE_RAM_ATTR
|
||||
#define VAR_ISR_ATTR
|
||||
#elif defined(ESP32)
|
||||
#define RECEIVE_ATTR IRAM_ATTR
|
||||
#define VAR_ISR_ATTR DRAM_ATTR
|
||||
#else
|
||||
#define RECEIVE_ATTR
|
||||
#define VAR_ISR_ATTR
|
||||
#endif
|
||||
|
||||
/* Format for protocol definitions:
|
||||
* {pulselength, Sync bit, "0" bit, "1" bit, invertedSignal}
|
||||
*
|
||||
* pulselength: pulse length in microseconds, e.g. 350
|
||||
* Sync bit: {1, 31} means 1 high pulse and 31 low pulses
|
||||
* (perceived as a 31*pulselength long pulse, total length of sync bit is
|
||||
* 32*pulselength microseconds), i.e:
|
||||
* _
|
||||
* | |_______________________________ (don't count the vertical bars)
|
||||
* "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse
|
||||
* and 3 low pulses, total length (1+3)*pulselength, i.e:
|
||||
* _
|
||||
* | |___
|
||||
* "1" bit: waveform for a data bit of value "1", e.g. {3,1}:
|
||||
* ___
|
||||
* | |_
|
||||
*
|
||||
* These are combined to form Tri-State bits when sending or receiving codes.
|
||||
*/
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
static const VAR_ISR_ATTR RCSwitch::Protocol proto[] = {
|
||||
#else
|
||||
static const RCSwitch::Protocol PROGMEM proto[] = {
|
||||
#endif
|
||||
{ 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1
|
||||
{ 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2
|
||||
{ 100, { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3
|
||||
{ 380, { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4
|
||||
{ 500, { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5
|
||||
{ 450, { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B)
|
||||
{ 150, { 2, 62 }, { 1, 6 }, { 6, 1 }, false }, // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote)
|
||||
{ 200, { 3, 130}, { 7, 16 }, { 3, 16}, false}, // protocol 8 Conrad RS-200 RX
|
||||
{ 200, { 130, 7 }, { 16, 7 }, { 16, 3 }, true}, // protocol 9 Conrad RS-200 TX
|
||||
{ 365, { 18, 1 }, { 3, 1 }, { 1, 3 }, true }, // protocol 10 (1ByOne Doorbell)
|
||||
{ 270, { 36, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 11 (HT12E)
|
||||
{ 320, { 36, 1 }, { 1, 2 }, { 2, 1 }, true } // protocol 12 (SM5212)
|
||||
};
|
||||
|
||||
void RCSwitch::gpio_callback(unsigned int gpio, uint32_t events) {
|
||||
RCSwitch::handleInterrupt();
|
||||
}
|
||||
|
||||
enum {
|
||||
numProto = sizeof(proto) / sizeof(proto[0])
|
||||
};
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
volatile unsigned long RCSwitch::nReceivedValue = 0;
|
||||
volatile unsigned int RCSwitch::nReceivedBitlength = 0;
|
||||
volatile unsigned int RCSwitch::nReceivedDelay = 0;
|
||||
volatile unsigned int RCSwitch::nReceivedProtocol = 0;
|
||||
int RCSwitch::nReceiveTolerance = 60;
|
||||
const unsigned int VAR_ISR_ATTR RCSwitch::nSeparationLimit = 4300;
|
||||
// separationLimit: minimum microseconds between received codes, closer codes are ignored.
|
||||
// according to discussion on issue #14 it might be more suitable to set the separation
|
||||
// limit to the same time as the 'low' part of the sync signal for the current protocol.
|
||||
unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
|
||||
#endif
|
||||
|
||||
RCSwitch::RCSwitch() {
|
||||
this->nTransmitterPin = -1;
|
||||
this->setRepeatTransmit(10);
|
||||
this->setProtocol(1);
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
this->nReceiverInterrupt = -1;
|
||||
this->setReceiveTolerance(60);
|
||||
RCSwitch::nReceivedValue = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol to send.
|
||||
*/
|
||||
void RCSwitch::setProtocol(Protocol protocol) {
|
||||
this->protocol = protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol to send, from a list of predefined protocols
|
||||
*/
|
||||
void RCSwitch::setProtocol(int nProtocol) {
|
||||
if (nProtocol < 1 || nProtocol > numProto) {
|
||||
nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ???
|
||||
}
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
this->protocol = proto[nProtocol-1];
|
||||
#else
|
||||
memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol to send with pulse length in microseconds.
|
||||
*/
|
||||
void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
|
||||
setProtocol(nProtocol);
|
||||
this->setPulseLength(nPulseLength);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets pulse length in microseconds
|
||||
*/
|
||||
void RCSwitch::setPulseLength(int nPulseLength) {
|
||||
this->protocol.pulseLength = nPulseLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Repeat Transmits
|
||||
*/
|
||||
void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
|
||||
this->nRepeatTransmit = nRepeatTransmit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Receiving Tolerance
|
||||
*/
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
void RCSwitch::setReceiveTolerance(int nPercent) {
|
||||
RCSwitch::nReceiveTolerance = nPercent;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Enable transmissions
|
||||
*
|
||||
* @param nTransmitterPin Arduino Pin to which the sender is connected to
|
||||
*/
|
||||
void RCSwitch::enableTransmit(int nTransmitterPin) {
|
||||
this->nTransmitterPin = nTransmitterPin;
|
||||
// pinMode(this->nTransmitterPin, OUTPUT);
|
||||
gpio_set_dir(this->nTransmitterPin,GPIO_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable transmissions
|
||||
*/
|
||||
void RCSwitch::disableTransmit() {
|
||||
this->nTransmitterPin = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch on (Type D REV)
|
||||
*
|
||||
* @param sGroup Code of the switch group (A,B,C,D)
|
||||
* @param nDevice Number of the switch itself (1..3)
|
||||
*/
|
||||
void RCSwitch::switchOn(char sGroup, int nDevice) {
|
||||
this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch off (Type D REV)
|
||||
*
|
||||
* @param sGroup Code of the switch group (A,B,C,D)
|
||||
* @param nDevice Number of the switch itself (1..3)
|
||||
*/
|
||||
void RCSwitch::switchOff(char sGroup, int nDevice) {
|
||||
this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch on (Type C Intertechno)
|
||||
*
|
||||
* @param sFamily Familycode (a..f)
|
||||
* @param nGroup Number of group (1..4)
|
||||
* @param nDevice Number of device (1..4)
|
||||
*/
|
||||
void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) {
|
||||
this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch off (Type C Intertechno)
|
||||
*
|
||||
* @param sFamily Familycode (a..f)
|
||||
* @param nGroup Number of group (1..4)
|
||||
* @param nDevice Number of device (1..4)
|
||||
*/
|
||||
void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) {
|
||||
this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch on (Type B with two rotary/sliding switches)
|
||||
*
|
||||
* @param nAddressCode Number of the switch group (1..4)
|
||||
* @param nChannelCode Number of the switch itself (1..4)
|
||||
*/
|
||||
void RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
|
||||
this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch off (Type B with two rotary/sliding switches)
|
||||
*
|
||||
* @param nAddressCode Number of the switch group (1..4)
|
||||
* @param nChannelCode Number of the switch itself (1..4)
|
||||
*/
|
||||
void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
|
||||
this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead!
|
||||
* Switch a remote switch on (Type A with 10 pole DIP switches)
|
||||
*
|
||||
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
* @param nChannelCode Number of the switch itself (1..5)
|
||||
*/
|
||||
void RCSwitch::switchOn(const char* sGroup, int nChannel) {
|
||||
const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||
this->switchOn(sGroup, code[nChannel]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead!
|
||||
* Switch a remote switch off (Type A with 10 pole DIP switches)
|
||||
*
|
||||
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
* @param nChannelCode Number of the switch itself (1..5)
|
||||
*/
|
||||
void RCSwitch::switchOff(const char* sGroup, int nChannel) {
|
||||
const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||
this->switchOff(sGroup, code[nChannel]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch on (Type A with 10 pole DIP switches)
|
||||
*
|
||||
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
* @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
*/
|
||||
void RCSwitch::switchOn(const char* sGroup, const char* sDevice) {
|
||||
this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch off (Type A with 10 pole DIP switches)
|
||||
*
|
||||
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
* @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
*/
|
||||
void RCSwitch::switchOff(const char* sGroup, const char* sDevice) {
|
||||
this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a char[13], representing the code word to be send.
|
||||
*
|
||||
*/
|
||||
char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus) {
|
||||
static char sReturn[13];
|
||||
int nReturnPos = 0;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0';
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0';
|
||||
}
|
||||
|
||||
sReturn[nReturnPos++] = bStatus ? '0' : 'F';
|
||||
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||
|
||||
sReturn[nReturnPos] = '\0';
|
||||
return sReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding for type B switches with two rotary/sliding switches.
|
||||
*
|
||||
* The code word is a tristate word and with following bit pattern:
|
||||
*
|
||||
* +-----------------------------+-----------------------------+----------+------------+
|
||||
* | 4 bits address | 4 bits address | 3 bits | 1 bit |
|
||||
* | switch group | switch number | not used | on / off |
|
||||
* | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 |
|
||||
* +-----------------------------+-----------------------------+----------+------------+
|
||||
*
|
||||
* @param nAddressCode Number of the switch group (1..4)
|
||||
* @param nChannelCode Number of the switch itself (1..4)
|
||||
* @param bStatus Whether to switch on (true) or off (false)
|
||||
*
|
||||
* @return char[13], representing a tristate code word of length 12
|
||||
*/
|
||||
char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) {
|
||||
static char sReturn[13];
|
||||
int nReturnPos = 0;
|
||||
|
||||
if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F';
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F';
|
||||
}
|
||||
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
|
||||
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||
|
||||
sReturn[nReturnPos] = '\0';
|
||||
return sReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like getCodeWord (Type C = Intertechno)
|
||||
*/
|
||||
char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) {
|
||||
static char sReturn[13];
|
||||
int nReturnPos = 0;
|
||||
|
||||
int nFamily = (int)sFamily - 'a';
|
||||
if ( nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// encode the family into four bits
|
||||
sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0';
|
||||
|
||||
// encode the device and group
|
||||
sReturn[nReturnPos++] = ((nDevice-1) & 1) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = ((nDevice-1) & 2) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = ((nGroup-1) & 1) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = ((nGroup-1) & 2) ? 'F' : '0';
|
||||
|
||||
// encode the status code
|
||||
sReturn[nReturnPos++] = '0';
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||
|
||||
sReturn[nReturnPos] = '\0';
|
||||
return sReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding for the REV Switch Type
|
||||
*
|
||||
* The code word is a tristate word and with following bit pattern:
|
||||
*
|
||||
* +-----------------------------+-------------------+----------+--------------+
|
||||
* | 4 bits address | 3 bits address | 3 bits | 2 bits |
|
||||
* | switch group | device number | not used | on / off |
|
||||
* | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 |
|
||||
* +-----------------------------+-------------------+----------+--------------+
|
||||
*
|
||||
* Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
|
||||
*
|
||||
* @param sGroup Name of the switch group (A..D, resp. a..d)
|
||||
* @param nDevice Number of the switch itself (1..3)
|
||||
* @param bStatus Whether to switch on (true) or off (false)
|
||||
*
|
||||
* @return char[13], representing a tristate code word of length 12
|
||||
*/
|
||||
char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) {
|
||||
static char sReturn[13];
|
||||
int nReturnPos = 0;
|
||||
|
||||
// sGroup must be one of the letters in "abcdABCD"
|
||||
int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A';
|
||||
if ( nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F';
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F';
|
||||
}
|
||||
|
||||
sReturn[nReturnPos++] = '0';
|
||||
sReturn[nReturnPos++] = '0';
|
||||
sReturn[nReturnPos++] = '0';
|
||||
|
||||
sReturn[nReturnPos++] = bStatus ? '1' : '0';
|
||||
sReturn[nReturnPos++] = bStatus ? '0' : '1';
|
||||
|
||||
sReturn[nReturnPos] = '\0';
|
||||
return sReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sCodeWord a tristate code word consisting of the letter 0, 1, F
|
||||
*/
|
||||
void RCSwitch::sendTriState(const char* sCodeWord) {
|
||||
// turn the tristate code word into the corresponding bit pattern, then send it
|
||||
unsigned long code = 0;
|
||||
unsigned int length = 0;
|
||||
for (const char* p = sCodeWord; *p; p++) {
|
||||
code <<= 2L;
|
||||
switch (*p) {
|
||||
case '0':
|
||||
// bit pattern 00
|
||||
break;
|
||||
case 'F':
|
||||
// bit pattern 01
|
||||
code |= 1L;
|
||||
break;
|
||||
case '1':
|
||||
// bit pattern 11
|
||||
code |= 3L;
|
||||
break;
|
||||
}
|
||||
length += 2;
|
||||
}
|
||||
this->send(code, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sCodeWord a binary code word consisting of the letter 0, 1
|
||||
*/
|
||||
void RCSwitch::send(const char* sCodeWord) {
|
||||
// turn the tristate code word into the corresponding bit pattern, then send it
|
||||
unsigned long code = 0;
|
||||
unsigned int length = 0;
|
||||
for (const char* p = sCodeWord; *p; p++) {
|
||||
code <<= 1L;
|
||||
if (*p != '0')
|
||||
code |= 1L;
|
||||
length++;
|
||||
}
|
||||
this->send(code, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmit the first 'length' bits of the integer 'code'. The
|
||||
* bits are sent from MSB to LSB, i.e., first the bit at position length-1,
|
||||
* then the bit at position length-2, and so on, till finally the bit at position 0.
|
||||
*/
|
||||
void RCSwitch::send(unsigned long code, unsigned int length) {
|
||||
if (this->nTransmitterPin == -1)
|
||||
return;
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
// make sure the receiver is disabled while we transmit
|
||||
int nReceiverInterrupt_backup = nReceiverInterrupt;
|
||||
if (nReceiverInterrupt_backup != -1) {
|
||||
this->disableReceive();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) {
|
||||
for (int i = length-1; i >= 0; i--) {
|
||||
if (code & (1L << i))
|
||||
this->transmit(protocol.one);
|
||||
else
|
||||
this->transmit(protocol.zero);
|
||||
}
|
||||
this->transmit(protocol.syncFactor);
|
||||
}
|
||||
|
||||
// Disable transmit after sending (i.e., for inverted protocols)
|
||||
// digitalWrite(this->nTransmitterPin, LOW);
|
||||
gpio_put(this->nTransmitterPin, LOW);
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
// enable receiver again if we just disabled it
|
||||
if (nReceiverInterrupt_backup != -1) {
|
||||
this->enableReceive(nReceiverInterrupt_backup);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmit a single high-low pulse.
|
||||
*/
|
||||
void RCSwitch::transmit(HighLow pulses) {
|
||||
uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH;
|
||||
uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW;
|
||||
|
||||
// digitalWrite(this->nTransmitterPin, firstLogicLevel);
|
||||
// delayMicroseconds( this->protocol.pulseLength * pulses.high);
|
||||
// digitalWrite(this->nTransmitterPin, secondLogicLevel);
|
||||
// delayMicroseconds( this->protocol.pulseLength * pulses.low);
|
||||
gpio_put(this->nTransmitterPin, firstLogicLevel);
|
||||
sleep_us(this->protocol.pulseLength * pulses.high);
|
||||
gpio_put(this->nTransmitterPin, secondLogicLevel);
|
||||
sleep_us(this->protocol.pulseLength * pulses.low);
|
||||
}
|
||||
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
/**
|
||||
* Enable receiving data
|
||||
*/
|
||||
void RCSwitch::enableReceive(int interrupt) {
|
||||
this->nReceiverInterrupt = interrupt;
|
||||
this->enableReceive();
|
||||
}
|
||||
|
||||
void RCSwitch::enableReceive() {
|
||||
if (this->nReceiverInterrupt != -1) {
|
||||
RCSwitch::nReceivedValue = 0;
|
||||
RCSwitch::nReceivedBitlength = 0;
|
||||
gpio_set_irq_enabled_with_callback(this->nReceiverInterrupt, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
|
||||
// attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable receiving data
|
||||
*/
|
||||
void RCSwitch::disableReceive() {
|
||||
#if not defined(RaspberryPi) // Arduino
|
||||
// detachInterrupt(this->nReceiverInterrupt);
|
||||
#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR
|
||||
this->nReceiverInterrupt = -1;
|
||||
}
|
||||
|
||||
bool RCSwitch::available() {
|
||||
return RCSwitch::nReceivedValue != 0;
|
||||
}
|
||||
|
||||
void RCSwitch::resetAvailable() {
|
||||
RCSwitch::nReceivedValue = 0;
|
||||
}
|
||||
|
||||
unsigned long RCSwitch::getReceivedValue() {
|
||||
return RCSwitch::nReceivedValue;
|
||||
}
|
||||
|
||||
unsigned int RCSwitch::getReceivedBitlength() {
|
||||
return RCSwitch::nReceivedBitlength;
|
||||
}
|
||||
|
||||
unsigned int RCSwitch::getReceivedDelay() {
|
||||
return RCSwitch::nReceivedDelay;
|
||||
}
|
||||
|
||||
unsigned int RCSwitch::getReceivedProtocol() {
|
||||
return RCSwitch::nReceivedProtocol;
|
||||
}
|
||||
|
||||
unsigned int* RCSwitch::getReceivedRawdata() {
|
||||
return RCSwitch::timings;
|
||||
}
|
||||
|
||||
/* helper function for the receiveProtocol method */
|
||||
static inline unsigned int diff(int A, int B) {
|
||||
return abs(A - B);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) {
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
const Protocol &pro = proto[p-1];
|
||||
#else
|
||||
Protocol pro;
|
||||
memcpy_P(&pro, &proto[p-1], sizeof(Protocol));
|
||||
#endif
|
||||
|
||||
unsigned long code = 0;
|
||||
//Assuming the longer pulse length is the pulse captured in timings[0]
|
||||
const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high);
|
||||
const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses;
|
||||
const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100;
|
||||
|
||||
/* For protocols that start low, the sync period looks like
|
||||
* _________
|
||||
* _____________| |XXXXXXXXXXXX|
|
||||
*
|
||||
* |--1st dur--|-2nd dur-|-Start data-|
|
||||
*
|
||||
* The 3rd saved duration starts the data.
|
||||
*
|
||||
* For protocols that start high, the sync period looks like
|
||||
*
|
||||
* ______________
|
||||
* | |____________|XXXXXXXXXXXXX|
|
||||
*
|
||||
* |-filtered out-|--1st dur--|--Start data--|
|
||||
*
|
||||
* The 2nd saved duration starts the data
|
||||
*/
|
||||
const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1);
|
||||
|
||||
for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) {
|
||||
code <<= 1;
|
||||
if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance &&
|
||||
diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) {
|
||||
// zero
|
||||
} else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance &&
|
||||
diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) {
|
||||
// one
|
||||
code |= 1;
|
||||
} else {
|
||||
// Failed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise
|
||||
RCSwitch::nReceivedValue = code;
|
||||
RCSwitch::nReceivedBitlength = (changeCount - 1) / 2;
|
||||
RCSwitch::nReceivedDelay = delay;
|
||||
RCSwitch::nReceivedProtocol = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RECEIVE_ATTR RCSwitch::handleInterrupt() {
|
||||
|
||||
static unsigned int changeCount = 0;
|
||||
static unsigned long lastTime = 0;
|
||||
static unsigned int repeatCount = 0;
|
||||
|
||||
// const long time = micros();
|
||||
const long time = to_us_since_boot(get_absolute_time());
|
||||
const unsigned int duration = time - lastTime;
|
||||
|
||||
if (duration > RCSwitch::nSeparationLimit) {
|
||||
|
||||
// A long stretch without signal level change occurred. This could
|
||||
// be the gap between two transmission.
|
||||
if ((repeatCount==0) || (diff(duration, RCSwitch::timings[0]) < 200)) {
|
||||
|
||||
// This long signal is close in length to the long signal which
|
||||
// started the previously recorded timings; this suggests that
|
||||
// it may indeed by a a gap between two transmissions (we assume
|
||||
// here that a sender will send the signal multiple times,
|
||||
// with roughly the same gap between them).
|
||||
repeatCount++;
|
||||
if (repeatCount == 2) {
|
||||
for(unsigned int i = 1; i <= numProto; i++) {
|
||||
if (receiveProtocol(i, changeCount)) {
|
||||
// receive succeeded for protocol i
|
||||
break;
|
||||
}
|
||||
}
|
||||
repeatCount = 0;
|
||||
}
|
||||
}
|
||||
changeCount = 0;
|
||||
}
|
||||
|
||||
// detect overflow
|
||||
if (changeCount >= RCSWITCH_MAX_CHANGES) {
|
||||
changeCount = 0;
|
||||
repeatCount = 0;
|
||||
}
|
||||
|
||||
RCSwitch::timings[changeCount++] = duration;
|
||||
lastTime = time;
|
||||
}
|
||||
#endif
|
170
433MHZ/rc-switch-pico/radio-switch.h
Normal file
170
433MHZ/rc-switch-pico/radio-switch.h
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
RCSwitch - Arduino libary for remote control outlet switches
|
||||
Copyright (c) 2011 Suat Özgür. All right reserved.
|
||||
|
||||
Contributors:
|
||||
- Andre Koehler / info(at)tomate-online(dot)de
|
||||
- Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
|
||||
- Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
|
||||
- Dominik Fischer / dom_fischer(at)web(dot)de
|
||||
- Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
|
||||
- Max Horn / max(at)quendi(dot)de
|
||||
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
|
||||
|
||||
Project home: https://github.com/sui77/rc-switch/
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _RCSwitch_h
|
||||
#define _RCSwitch_h
|
||||
|
||||
|
||||
// #define RaspberryPi
|
||||
|
||||
// Include libraries for RPi:
|
||||
#include <string.h> /* memcpy */
|
||||
#include <stdlib.h> /* abs */
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Number of maximum high/Low changes per packet.
|
||||
// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
|
||||
#define RCSWITCH_MAX_CHANGES 67
|
||||
|
||||
class RCSwitch {
|
||||
|
||||
public:
|
||||
RCSwitch();
|
||||
|
||||
void switchOn(int nGroupNumber, int nSwitchNumber);
|
||||
void switchOff(int nGroupNumber, int nSwitchNumber);
|
||||
void switchOn(const char* sGroup, int nSwitchNumber);
|
||||
void switchOff(const char* sGroup, int nSwitchNumber);
|
||||
void switchOn(char sFamily, int nGroup, int nDevice);
|
||||
void switchOff(char sFamily, int nGroup, int nDevice);
|
||||
void switchOn(const char* sGroup, const char* sDevice);
|
||||
void switchOff(const char* sGroup, const char* sDevice);
|
||||
void switchOn(char sGroup, int nDevice);
|
||||
void switchOff(char sGroup, int nDevice);
|
||||
|
||||
void sendTriState(const char* sCodeWord);
|
||||
void send(unsigned long code, unsigned int length);
|
||||
void send(const char* sCodeWord);
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
void enableReceive(int interrupt);
|
||||
void enableReceive();
|
||||
void disableReceive();
|
||||
bool available();
|
||||
void resetAvailable();
|
||||
|
||||
unsigned long getReceivedValue();
|
||||
unsigned int getReceivedBitlength();
|
||||
unsigned int getReceivedDelay();
|
||||
unsigned int getReceivedProtocol();
|
||||
unsigned int* getReceivedRawdata();
|
||||
#endif
|
||||
|
||||
void enableTransmit(int nTransmitterPin);
|
||||
void disableTransmit();
|
||||
void setPulseLength(int nPulseLength);
|
||||
void setRepeatTransmit(int nRepeatTransmit);
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
void setReceiveTolerance(int nPercent);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Description of a single pule, which consists of a high signal
|
||||
* whose duration is "high" times the base pulse length, followed
|
||||
* by a low signal lasting "low" times the base pulse length.
|
||||
* Thus, the pulse overall lasts (high+low)*pulseLength
|
||||
*/
|
||||
struct HighLow {
|
||||
uint8_t high;
|
||||
uint8_t low;
|
||||
};
|
||||
|
||||
/**
|
||||
* A "protocol" describes how zero and one bits are encoded into high/low
|
||||
* pulses.
|
||||
*/
|
||||
struct Protocol {
|
||||
/** base pulse length in microseconds, e.g. 350 */
|
||||
uint16_t pulseLength;
|
||||
|
||||
HighLow syncFactor;
|
||||
HighLow zero;
|
||||
HighLow one;
|
||||
|
||||
/**
|
||||
* If true, interchange high and low logic levels in all transmissions.
|
||||
*
|
||||
* By default, RCSwitch assumes that any signals it sends or receives
|
||||
* can be broken down into pulses which start with a high signal level,
|
||||
* followed by a a low signal level. This is e.g. the case for the
|
||||
* popular PT 2260 encoder chip, and thus many switches out there.
|
||||
*
|
||||
* But some devices do it the other way around, and start with a low
|
||||
* signal level, followed by a high signal level, e.g. the HT6P20B. To
|
||||
* accommodate this, one can set invertedSignal to true, which causes
|
||||
* RCSwitch to change how it interprets any HighLow struct FOO: It will
|
||||
* then assume transmissions start with a low signal lasting
|
||||
* FOO.high*pulseLength microseconds, followed by a high signal lasting
|
||||
* FOO.low*pulseLength microseconds.
|
||||
*/
|
||||
bool invertedSignal;
|
||||
};
|
||||
|
||||
void setProtocol(Protocol protocol);
|
||||
void setProtocol(int nProtocol);
|
||||
void setProtocol(int nProtocol, int nPulseLength);
|
||||
|
||||
private:
|
||||
static void gpio_callback(unsigned int gpio, uint32_t events);
|
||||
char* getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus);
|
||||
char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus);
|
||||
char* getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus);
|
||||
char* getCodeWordD(char group, int nDevice, bool bStatus);
|
||||
void transmit(HighLow pulses);
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
static void handleInterrupt();
|
||||
static bool receiveProtocol(const int p, unsigned int changeCount);
|
||||
int nReceiverInterrupt;
|
||||
#endif
|
||||
int nTransmitterPin;
|
||||
int nRepeatTransmit;
|
||||
|
||||
Protocol protocol;
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
static int nReceiveTolerance;
|
||||
volatile static unsigned long nReceivedValue;
|
||||
volatile static unsigned int nReceivedBitlength;
|
||||
volatile static unsigned int nReceivedDelay;
|
||||
volatile static unsigned int nReceivedProtocol;
|
||||
const static unsigned int nSeparationLimit;
|
||||
/*
|
||||
* timings[0] contains sync timing, followed by a number of bits
|
||||
*/
|
||||
static unsigned int timings[RCSWITCH_MAX_CHANGES];
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
23
433MHZ/rc-switch-pico/readme.md
Normal file
23
433MHZ/rc-switch-pico/readme.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# RcSwitch
|
||||
A port of the brilliant [RC-Switch](https://github.com/sui77/rc-switch) library to the raspberry pi pico.
|
||||
|
||||
It allows you to send and recieve radio signals from 433/315Mhz devices like radio controlled power sockets, using cheap radio modules.
|
||||
|
||||
This works for both recieving and transmitting. Check out the examples for code for both of these.
|
||||
|
||||
## Building
|
||||
This library can be developed on any platform that the pico-sdk works on, through cmake.
|
||||
|
||||
In the root directory, make sure that the pico-sdk is on your path and run
|
||||
```bash
|
||||
cmake .
|
||||
```
|
||||
|
||||
then change directory into `examples/recieve`, then run
|
||||
```bash
|
||||
make
|
||||
```
|
||||
which will spit out your uf2 file.
|
||||
|
||||
## Issues
|
||||
If you experience an error while using this library, please raise an issue here on Github and I'll try to help out. Pull requests are also very welcome!
|
Reference in New Issue
Block a user