diff --git a/.github/workflows/CompileTests.yml b/.github/workflows/CompileTests.yml new file mode 100644 index 0000000..73f8d42 --- /dev/null +++ b/.github/workflows/CompileTests.yml @@ -0,0 +1,109 @@ +# This is the name of the workflow, visible on GitHub UI. +name: 'Compile tests' + +#description: 'Run the Arduino CLI to compile the sketch and check if it compiles fine for multiple boards' +#author: 'Jorge Rivera' + +# Controls when the action will run. +# Here we tell GitHub to run the workflow when a commit. +on: + # Triggers the workflow on push or pull request events but only for the "arduino" branch + push: + branches: [ arduino ] + paths: + - '*.ino' + - '.github/workflows/*.yml' + + pull_request: + branches: [ arduino ] + paths: + - '*.ino' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# This is the list of jobs that will be run concurrently. +# Since we use a build matrix, the actual number of jobs +# started depends on how many configurations the matrix +# will produce. +jobs: + boards: + + # This is the name of the job + name: "Compile test for ${{ matrix.config.board }}" + + # This is the platform GitHub will use to run our workflow, we + # pick Linux for no particular reason. + runs-on: ubuntu-latest + + # Here we tell GitHub that the jobs must be determined + # dynamically depending on a matrix configuration. + strategy: + + # Set to false so that GitHub does not cancel all jobs + # in progress if any array job fails. + fail-fast: false + + # The matrix will produce one job for each configuration: + matrix: + config: + - board: "Arduino Nano" + fqbn: "arduino:avr:nano" + platform: "arduino:avr" + + - board: "Arduino UNO" + fqbn: "arduino:avr:uno" + platform: "arduino:avr" + + - board: "Arduino Leonardo" + fqbn: "arduino:avr:leonardo" + platform: "arduino:avr" + + - board: "Arduino Due (Native USB Port)" + fqbn: "arduino:sam:arduino_due_x" + platform: "arduino:sam" + + - board: "Arduino M0" + fqbn: "arduino:samd:mzero_bl" + platform: "arduino:samd" + + - board: "ESP8266 NodeMCUv2" + fqbn: "esp8266:esp8266:nodemcuv2" + platform: "esp8266:esp8266" + additional-url: "--additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json" + + - board: "ESP32 NodeMCU-32S" + fqbn: "esp32:esp32:nodemcu-32s" + platform: "esp32:esp32" + additional-url: "--additional-urls https://dl.espressif.com/dl/package_esp32_index.json" + + # This is the list of steps this job will run. + steps: + # First of all, we clone the repo using the "checkout" action. + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - name: Checkout + uses: actions/checkout@v4 + + # We use the "arduino/setup-arduino-cli" action to install and + # configure the Arduino CLI on the system. + - name: Setup Arduino CLI + uses: arduino/setup-arduino-cli@v2 + + # We then install the platform, which one will be determined + # dynamically by the build matrix. + - name: Install platform ${{ matrix.config.platform }} + run: | + arduino-cli config init -v ${{ matrix.config.additional-url }} + arduino-cli core update-index -v + arduino-cli core install -v ${{ matrix.config.platform }} --run-post-install + + # Finally, we compile the sketch, using the FQBN that was set in the build matrix. + - name: Compile sketch for ${{ matrix.config.board }} + run: arduino-cli compile -v --fqbn ${{ matrix.config.fqbn }} --export-binaries --warnings none --log-level info + + # Upload binary (.hex) files to artifacts + - name: Upload compiled binaries files to Artifacts + uses: actions/upload-artifact@v4 + with: + name: "Binaries for ${{ matrix.config.board }}" + path: ./ diff --git a/.gitignore b/.gitignore index edf6645..6ff2b5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,35 @@ +# Compiler outputs +build/* + +# Visual Studio Code +.vscode/ +*.code-workspace +.history/ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +Thumbs.db + +# Prerequisites +*.d + +# Precompiled Headers +*.gch +*.pch + # Object files *.o *.ko *.obj *.elf +*.bin +*.eep +*.lo +*.slo # Precompiled Headers *.gch @@ -12,7 +39,7 @@ *.lib *.a *.la -*.lo +*.lai # Shared objects (inc. Windows DLLs) *.dll diff --git a/README.md b/README.md index f0a6f32..0db45fc 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,50 @@ -# pilight USB Nano +# pilight USB Nano v2 (Arduino compatible) -The pilight Arduino Nano software allows any computer with an USB port to work with pilight. +The pilight USB Nano software allows any computer with an USB port to work with pilight. + +[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) +[![Compile tests](https://github.com/latchdevel/pilight-usb-nano/actions/workflows/CompileTests.yml/badge.svg?branch=arduino)](https://github.com/latchdevel/pilight-usb-nano/actions/workflows/CompileTests.yml) + +## New v2 firmware features: + - Can run on any AVR Arduino compatible board, like Arduino UNO, Nano, MEGA, Leonardo, etc. any clock speed allowed. + - Can run on other platforms like Arduino SAMD boards (DUE, M0, etc.), ESP8266, ESP32, Teensy, even Raspberry Pico. + - Works using the MCU's internal USB-Serial COM port (CDC/ACM device class) or any onboard/external USB-Serial adapter. + - Fully Arduino IDE compiler environment compatible. Arduino PRO IDE and Arduino CLI also supported. + - Configurable RF receiver output (RX_PIN); must be interrupt attachable, depends board (D2 as default). + - Configurable RF transmitter input (TX_PIN); can be any digital pin, depends board (D5 as default). + - Support to configure a digital output so that a led blinks at valid RF code reception. + - Support to configure send of every 'space' before 'pulse', which stripped in previous version firmware. + - Support to configure initial RX settings at boot, like as 's:22,200,3000,51000@'. + - Support to configure show settings at boot, like as: 'v:20,200,4000,82000,2,1,1600@'. + - Support to configure add line feed '\n' each line output. + - Support to configure a tx enable pin (PTT_PIN), useful for use transceivers. + - Fix TX pulse generator drift from 9.95µS to 0.69µS (AVR@16Mhz). + - Improve RX pulse meter resolution from 10µS to 4µS (AVR@16Mhz). + +## Usage: 1. Compile the firmware: -``` -avr-gcc -Os -Wall -DF_CPU=16000000UL -mmcu=atmega328p -c -o pilight_usb_nano.o pilight_usb_nano.c -lm -I. -avr-gcc -mmcu=atmega328p pilight_usb_nano.o -o pilight_usb_nano -avr-objcopy -O ihex -R .eeprom pilight_usb_nano pilight_usb_nano.hex -``` -2. Flash the firmware on the Arduino Nano: -`avrdude -b 57600 -p atmega328p -c arduino -P COM5 -U flash:w:pilight_usb_nano.hex` -3. Connect the receiver data pin to D2 and the sender to D5. -4. Connect the Arduino Nano to your computer. -5. Check what COM port the Arduino Nano is using. -6. Configure pilight to interface with the Arduino Nano (see below). + ``` + - Open Arduino IDE application + - File> Open> Select file "pilight-usb-nano.ino" + - Tools> Board> Select your board + - Sketch> Verify/Compile + ``` +2. Flash the firmware on the board: + ``` + - Tools> Port> Select your USB/Serial COM port + - Sketch> Upload + ``` +3. Connect the receiver data pin to configured RX_PIN (D2 as default) and the transmitter data pin to configured TX_PIN (D5 as default). +4. Connect the Arduino to your computer. +5. Check what Serial/COM port the Arduino is using. +6. Configure pilight to interface with the Arduino (see below). 7. Start pilight normally and it should work OOTB. -pilight USB nano hardware configuration: +## pilight USB Arduino hardware configuration: Linux example: -``` +```json "hardware": { "433nano": { "comport": "/dev/ttyUSB0" @@ -27,10 +52,76 @@ Linux example: } ``` Windows Example: -``` +```json "hardware": { "433nano": { "comport": "COM5" } } -``` \ No newline at end of file +``` + +## Example: +Transmitter code: +``` +c:011010100101011010100110101001100110010101100110101010101010101012;p:1400,600,6800;r:4@ +``` + * Receive with spaces: + ``` + c:011010100101011010100110101001100110010101100110101010101010101012;p:1400,600,6800@ + ``` + + * Receive without spaces: + ``` + c:100011100010001010111010000000002;p:1400,600,6800@ + ``` + +## Decoding: +You can decode and encode any code using an external tool **"picoder"** from https://github.com/latchdevel/picoder + +Decode example: +``` +$ picoder decode -s "c:011010100101011010100110101001100110010101100110101010101010101012;p:1400,600,6800@" +``` +return: +```json + [{ + "conrad_rsl_switch": { + "id": 1, + "unit": 2, + "state": "on" + } + }] +``` + +Encode example: +```json +$ picoder encode -f '{ "conrad_rsl_switch" : {"id":1,"unit":2,"on":1} }' -r 5 +``` +return: +``` +c:011010100101011010100110101001100110010101100110101010101010101012;p:1400,600,6800;r:5@ +``` + +## To do: +- [ ] Support to measure RSSI of receivers that provide it. + +# License + +Copyright (C) 2015 CurlyMo. This file is part of pilight. GPLv3. + +Copyright (C) 2021 Jorge Rivera. GNU General Public License v3.0. + +This program 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 3 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 . + + diff --git a/diff b/diff deleted file mode 100644 index 48ba9d9..0000000 --- a/diff +++ /dev/null @@ -1,377 +0,0 @@ -diff --git a/README.md b/README.md -index 5c180cc..e669d2e 100644 ---- a/README.md -+++ b/README.md -@@ -1,2 +1,31 @@ --# pilight-usb-nano --pilight Arduino Nano USB interface -+# pilight USB Nano -+ -+The pilight Arduino Nano software allows any computer with an USB port to work with pilight. -+ -+1. Compile the firmware: -+`avr-gcc -Os -Wall -DF_CPU=16000000UL -mmcu=atmega328p -c -o usbto433.o usbto433.c -lm -I.` -+`avr-gcc -mmcu=atmega328p usbto433.o -o usbto433` -+`avr-objcopy -O ihex -R .eeprom usbto433 usbto433.hex` -+2. Flash the firmware on the Arduino Nano: -+`avrdude -b 57600 -p atmega328p -c arduino -P COM5 -U flash:w:usbto433.hex` -+3. Connect the receiver data pin to D2 and the sender to D5. -+4. Connect the Arduino Nano to your computer. -+5. Check what COM port the Arduino Nano is using. -+6. Configure pilight to interface with the Arduino Nano: -+Linux example: -+``` -+ "hardware": { -+ "433nano": { -+ "comport": "/dev/ttyUSB0" -+ } -+ } -+``` -+Windows Example: -+``` -+ "hardware": { -+ "433nano": { -+ "comport": "COM5" -+ } -+ } -+``` -+7. Start pilight normally and it should work OOTB. -\ No newline at end of file -diff --git a/usbto433.c b/usbto433.c -new file mode 100644 -index 0000000..ce83dcf ---- /dev/null -+++ b/usbto433.c -@@ -0,0 +1,332 @@ -+/* -+ Copyright (C) 2015 CurlyMo -+ -+ This file is part of pilight. -+ -+ pilight 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 3 of the License, or (at your option) any later -+ version. -+ -+ pilight 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 pilight. If not, see -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define BUFFER_SIZE 256 -+#define MAX_PULSE_TYPES 10 -+#define BAUD 57600 -+#define MIN_PULSELENGTH 8 //tested to work down to 30us pulsewidth (=2) -+#define MAX_PULSELENGTH 1600 -+#define MIN_FOOTER_LENGTH 510 // 5100 deviced by 10 -+#define MIN_STREAM_LENGTH 25 -+ -+#include -+ -+// Code formatting meant for sending -+// on c:102020202020202020220202020020202200202200202020202020220020202203;p:279,2511,1395,9486;r:5@ -+// off c:102020202020202020220202020020202200202200202020202020202020202203;p:279,2511,1395,9486;r:5@ -+ -+ -+// Code formatting outputted by receiver -+// on c:102020202020202020220202020020202200202200202020202020220020202203;p:279,2511,1395,9486@ -+// off c:102020202020202020220202020020202200202200202020202020202020202203;p:279,2511,1395,9486@ -+ -+char data[BUFFER_SIZE]; -+volatile unsigned long ten_us_counter1 = 0; -+volatile uint16_t ten_us_counter = 0, codes[BUFFER_SIZE], plstypes[MAX_PULSE_TYPES]; -+volatile uint8_t state = 0, codelen = 0, repeats = 0, pos = 0; -+volatile uint8_t valid_buffer = 0x00, r = 0, q = 0, plslen = 0, nrpulses = 0; -+ -+void initUART(void) { -+ DDRD |= _BV(PD1); -+ DDRD &= ~_BV(PD0); -+ -+ UBRR0H = UBRRH_VALUE; -+ UBRR0L = UBRRL_VALUE; -+ -+#if USE_2X -+ UCSR0A |= _BV(U2X0); -+#else -+ UCSR0A &= ~_BV(U2X0); -+#endif -+ -+ UCSR0B |= _BV(RXEN0); -+ UCSR0B |= _BV(RXCIE0); -+ // UCSR0B = UCSR0B | (1 << TXEN0); -+ -+ UCSR0C |= _BV(USBS0); -+ UCSR0C |= _BV(UCSZ01) | _BV(UCSZ00); -+} -+ -+void setup() { -+ uint8_t oldSREG = SREG; -+ -+ cli(); -+ -+ /* We initialize our array to zero -+ * here to spare resources while -+ * running. -+ */ -+ for(r=0;r 0 && spulse > 0 && srepeat > 0) { -+ z = strlen(&data[spulse]); -+ s = spulse; -+ nrpulses = 0; -+ for(i = spulse; i < spulse + z; i++) { -+ if(data[i] == ',') { -+ data[i] = '\0'; -+ plstypes[nrpulses++] = atoi(&data[s]); -+ s = i+1; -+ } -+ } -+ plstypes[nrpulses++] = atoi(&data[s]); -+ -+ codelen = strlen(&data[scode]); -+ repeats = atoi(&data[srepeat]); -+ cli(); -+ for(i=0;i 100000) { -+ putByte('\n'); -+ ten_us_counter1 = 0; -+ } -+ sei(); -+} -+ -+void broadcast() { -+ int i = 0, x = 0, match = 0, p = 0; -+ -+ putByte('c'); -+ putByte(':'); -+ for(i=0;i MIN_PULSELENGTH) { -+ if(ten_us_counter < MAX_PULSELENGTH) { -+ /* All codes are buffered */ -+ codes[nrpulses++] = ten_us_counter; -+ if(nrpulses > BUFFER_SIZE) { -+ nrpulses = 0; -+ } -+ /* Let's match footers */ -+ if(ten_us_counter > MIN_FOOTER_LENGTH) { -+ /* Only match minimal length pulse streams */ -+ if(nrpulses >= MIN_STREAM_LENGTH) { -+ /* -+ * Sending pulses over serial requires -+ * a lot of cpu ticks. We therefor have -+ * to be sure that we send valid codes. -+ * Therefor, only streams we at least -+ * received twice communicated. -+ */ -+ if(plslen == nrpulses) { -+ broadcast(); -+ } -+ plslen = nrpulses; -+ } -+ nrpulses = 0; -+ } -+ } -+ } -+ ten_us_counter = 0; -+ TCNT1 = 0; -+ sei(); -+} -+ -+int main(void) { -+ setup(); -+ while(1); -+} diff --git a/pilight-usb-nano.ino b/pilight-usb-nano.ino new file mode 100644 index 0000000..f72650e --- /dev/null +++ b/pilight-usb-nano.ino @@ -0,0 +1,396 @@ +/* + Copyright (C) 2015 CurlyMo + This file is part of pilight. GNU General Public License v3.0. + + You should have received a copy of the GNU General Public License + along with pilight. If not, see + + Copyright (C) 2021 Jorge Rivera. GNU General Public License v3.0. + + New v2 firmware features: + - Can run on any AVR Arduino compatible board, like Arduino UNO, Nano, Mega, Leonardo, etc. + - Can run on other platforms like Arduino SAMD boards (DUE, M0, etc.), ESP8266, ESP32, Teensy, even Raspberry Pico. + - Fully Arduino IDE compiler environment compatible. Arduino PRO IDE and Arduino CLI also supported. + - Configurable RF receiver output (RX_PIN); must be interrupt attachable, depends board (D2 as default). + - Configurable RF transmitter input (TX_PIN); can be any digital pin, depends board (D5 as default). + - Support to configure a digital output so that a led blinks at valid RF code reception. + - Support to configure send of every 'space' before 'pulse', which stripped in previous version firmware. + - Support to configure initial RX settings at boot, like as 's:20,200,4000,82000@'. + - Support to configure show settings at boot, like as: 'v:20,200,4000,82000,2,1,1600@'. + - Support to configure add line feed '\n' each line output. + - Support to configure a tx enable pin (PTT_PIN), useful for use transceivers. + +*/ + +/* Configurable RX & TX pins */ +#define RX_PIN 2 // Pin for ASK/OOK pulse input from RF receiver module data output. +#define TX_PIN 5 // Pin for ASK/OOK pulse output to RF transmitter module data input. +#define PTT_PIN 4 // If a pin is defined, it will set to high state during transmissions. + +#define EVERY_SEC_LINE_FEED // If defined, print line feed '\n' every second, to emulate legacy firmware. +//#define SEND_STRIPPED_SPACES // If defined, send every 'space' before 'pulse' in broadcast(), which stripped in legacy firmware. +//#define LED_BLINK_RX LED_BUILTIN // If defined, sets the digital output to blink on valid RF code reception. +//#define DEFAULT_RX_SETTINGS // If defined, sets valid RX settings at boot, like sets 's:20,200,4000,82000@' +//#define BOOT_SHOW_SETTINGS // If defined, show settings at boot, like as: 'v:20,200,4000,82000,2,1,1600@' +//#define ADD_LINE_FEED // If defined, add line feed '\n' each line output. + +#define BUFFER_SIZE 256 // Warning: 256 max because buffer indexes "nrpulses" and "q" are "uint8_t" type +#define MAX_PULSE_TYPES 10 // From 0 to 9 +#define BAUD 57600 + +/* Show numbers devided by 10 */ +#define MIN_PULSELENGTH 6 // v2 change from 8 to 6 and show devided by 10 +#define MAX_PULSELENGTH 8200 // v2 change from 1600 to 8200 (for quigg_gt7000 protocol footer pulse around 81000 usecs) + +#define VERSION 2 // Version 2 (Arduino compatible) + +#ifdef DEFAULT_RX_SETTINGS +uint8_t minrawlen = 20; // Minimum number of pulses +uint8_t maxrawlen = 200; // Maximum number of pulses +uint16_t mingaplen = 400; // Minimum length of footer pulse and maximum length of previous pulses. Used and showing multiplied by 10 +#else +uint8_t minrawlen = UINT8_MAX; // Maximum value for uint8_t from (stdint.h) +uint8_t maxrawlen = 0; +uint16_t mingaplen = 10000; // Used and showing multiplied by 10 +#endif + +uint16_t maxgaplen = MAX_PULSELENGTH; // v2 used and change from 5100 to MAX_PULSELENGTH, set and show multiplied by 10 + +// Code formatting meant for sending +// on c:102020202020202020220202020020202200202200202020202020220020202203;p:279,2511,1395,9486;r:5@ +// off c:102020202020202020220202020020202200202200202020202020202020202203;p:279,2511,1395,9486;r:5@ + +// Code formatting outputted by receiver +// on c:102020202020202020220202020020202200202200202020202020220020202203;p:279,2511,1395,9486@ +// off c:102020202020202020220202020020202200202200202020202020202020202203;p:279,2511,1395,9486@ + +char data[BUFFER_SIZE] = {0}; // Fill to 0 // Buffer for serial uart inputs and outputs +volatile uint16_t codes[BUFFER_SIZE] = {0}; // Fill to 0 // Buffer to store pulses length + uint32_t plstypes[MAX_PULSE_TYPES] = {0}; // Fill to 0 // Buffer to store pulse types (RX and TX) +volatile uint32_t new_counter = 0; // Global time counter to store initial pulse micros(). Replaces global ten_us_counter. + +volatile uint8_t q = 0; // Index of data buffer +volatile uint8_t rawlen = 0; // Flag to ensure to call broadcast() after reveive two same lenght pulse train +volatile uint8_t nrpulses = 0; // Index of pulse lenght buffer +volatile uint8_t broadcast_flag = 0; // Flag to call broadcast with nrpulses value +volatile uint8_t receive_flag = 0; // Flag to call receive() in loop() + +void ISR_RX(); // Generic ISR function declaration for RF RX pulse interrupt handler instead specific AVR ISR(vector, attributes) + +void setup() { + + pinMode(TX_PIN, OUTPUT); + +#ifdef LED_BLINK_RX + pinMode(LED_BLINK_RX, OUTPUT); +#endif + +#ifdef PTT_PIN + // If defined PTT PIN set output low + pinMode(PTT_PIN,OUTPUT); + digitalWrite(PTT_PIN,LOW); +#endif + + // Arduino built-in function to attach Interrupt Service Routines (depends board) + attachInterrupt(digitalPinToInterrupt(RX_PIN), ISR_RX, CHANGE); + + // Arduino build-in function to set serial UART data baud rate (depends board) + Serial.begin(BAUD); + +#ifdef BOOT_SHOW_SETTINGS + // Show settings at boot, like as: 'v:20,200,4000,82000,2,1,1600@' + sprintf(data, "v:%u,%u,%lu,%lu,%d,%d,%d@", minrawlen, maxrawlen, uint32_t(mingaplen)*10, uint32_t(maxgaplen)*10, VERSION, MIN_PULSELENGTH/10, MAX_PULSELENGTH); +#ifdef ADD_LINE_FEED + Serial.println(data); +#else + Serial.print(data); +#endif +#endif + +} + +/* Everything is parsed on-the-fly to preserve memory */ +void receive() { + unsigned int scode = 0, spulse = 0, srepeat = 0, sstart = 0; + unsigned int i = 0, s = 0, z = 0, x = 0; + + nrpulses = 0; + + z = strlen(data); + for(i = 0; i < z; i++) { + if(data[i] == 's') { + sstart = i + 2; + break; + } + if(data[i] == 'c') { + scode = i + 2; + } + if(data[i] == 'p') { + spulse = i + 2; + } + if(data[i] == 'r') { + srepeat = i + 2; + } + if(data[i] == ';') { + data[i] = '\0'; + } + } + /* + * Tune the firmware with pilight-daemon values + */ + if(sstart > 0) { + z = strlen(&data[sstart]); + s = sstart; + x = 0; + for(i = sstart; i < sstart + z; i++) { + if(data[i] == ',') { + data[i] = '\0'; + if(x == 0) { + minrawlen = uint8_t(atoi(&data[s])); + } + if(x == 1) { + maxrawlen = uint8_t(atoi(&data[s])); + } + if(x == 2) { + mingaplen = uint16_t(atol(&data[s])/10); + } + x++; + s = i+1; + } + } + if(x == 3) { + maxgaplen = uint16_t(atol(&data[s])/10); + } + /* + * Once we tuned our firmware send back our settings + fw version + */ + sprintf(data, "v:%u,%u,%lu,%lu,%d,%d,%d@", minrawlen, maxrawlen, uint32_t(mingaplen)*10, uint32_t(maxgaplen)*10, VERSION, MIN_PULSELENGTH/10, MAX_PULSELENGTH); +#ifdef ADD_LINE_FEED + Serial.println(data); +#else + Serial.print(data); +#endif + } else if(scode > 0 && spulse > 0 && srepeat > 0) { + z = strlen(&data[spulse]); + s = spulse; + nrpulses = 0; + for(i = spulse; i < spulse + z; i++) { + if(data[i] == ',') { + data[i] = '\0'; + plstypes[nrpulses++] = atol(&data[s]); + s = i+1; + } + } + plstypes[nrpulses++] = atol(&data[s]); + s = strlen(&data[scode]); + x = (unsigned int)atoi(&data[srepeat]); + + // Check for maxgaplen + for(z = scode; z < scode + s; z++) { + if (plstypes[data[z] - '0'] >= uint32_t(maxgaplen*10)){ + // Clear pulse types array + for(i=0;i MIN_PULSELENGTH) { + if(ten_us_counter < MAX_PULSELENGTH) { + /* All codes are buffered */ + codes[nrpulses++] = ten_us_counter; + if(nrpulses >= BUFFER_SIZE-1) { + nrpulses = 0; + } + /* Let's match footers */ + if((ten_us_counter > mingaplen) and (ten_us_counter < maxgaplen)) { + /* Only match minimal length pulse streams */ + if(nrpulses >= minrawlen && nrpulses <= maxrawlen) { + /* + * Sending pulses over serial requires + * a lot of cpu ticks. We therefor have + * to be sure that we send valid codes. + * Therefor, only streams we at least + * received twice communicated. + */ + if(rawlen == nrpulses) { + broadcast_flag = nrpulses; + } + rawlen = nrpulses; + } + nrpulses = 0; + } + } + } +} + +void loop(){ + + // Workaround for Leonardo, Micro, and others MCUs like ESP8266 and ESP32 +#ifndef HAVE_HWSERIAL0 + if (Serial.available()) serialEvent(); +#endif + + // if receive flag is set + if (receive_flag){ + // Call to receive() + receive(); + // Clear flag + receive_flag = 0; + } + + // if broadcast flag is set + if (broadcast_flag > 0){ + +#ifdef LED_BLINK_RX + digitalWrite(LED_BLINK_RX, HIGH); // Led blink on RF RX +#endif + + // Call to broadcast() + broadcast(broadcast_flag); + // Clear flag + broadcast_flag = 0; + +#ifdef LED_BLINK_RX + digitalWrite(LED_BLINK_RX, LOW); // Led blink on RF RX +#endif + } + +#ifdef EVERY_SEC_LINE_FEED + static unsigned long line_feed_counter = 0; + if (millis() > line_feed_counter){ + line_feed_counter = millis()+1000; + Serial.println(); + } +#endif +} diff --git a/pilight_usb_nano.c b/pilight_usb_nano.c deleted file mode 100644 index 30481b6..0000000 --- a/pilight_usb_nano.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - Copyright (C) 2015 CurlyMo - - This file is part of pilight. - - pilight 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 3 of the License, or (at your option) any later - version. - - pilight 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 pilight. If not, see -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BUFFER_SIZE 256 -#define MAX_PULSE_TYPES 10 -#define BAUD 57600 -/* Number devided by 10 */ -#define MIN_PULSELENGTH 8 //tested to work down to 30us pulsewidth (=2) -#define MAX_PULSELENGTH 1600 -#define VERSION 1 - -volatile uint32_t minrawlen = 1000; -volatile uint32_t maxrawlen = 0; -volatile uint32_t mingaplen = 10000; -volatile uint32_t maxgaplen = 5100; - -const uint16_t MIN_2X_BAUD = F_CPU / (4 * (2 * 0XFFF + 1)) + 1; - -#include - -// Code formatting meant for sending -// on c:102020202020202020220202020020202200202200202020202020220020202203;p:279,2511,1395,9486;r:5@ -// off c:102020202020202020220202020020202200202200202020202020202020202203;p:279,2511,1395,9486;r:5@ - -// Code formatting outputted by receiver -// on c:102020202020202020220202020020202200202200202020202020220020202203;p:279,2511,1395,9486@ -// off c:102020202020202020220202020020202200202200202020202020202020202203;p:279,2511,1395,9486@ - -char data[BUFFER_SIZE]; -volatile unsigned long ten_us_counter1 = 0; -volatile uint16_t ten_us_counter = 0, codes[BUFFER_SIZE], plstypes[MAX_PULSE_TYPES]; -volatile uint8_t state = 0, codelen = 0, repeats = 0, pos = 0; -volatile uint8_t valid_buffer = 0x00, r = 0, q = 0, rawlen = 0, nrpulses = 0; - -void initUART(void) { - uint16_t x = 0; - - if((F_CPU != 16000000UL || BAUD != 57600) && BAUD > MIN_2X_BAUD) { - UCSR0A = 1 << U2X0; - x = (F_CPU / 4 / BAUD - 1) / 2; - } else { - UCSR0A = 0; - x = (F_CPU / 8 / BAUD - 1) / 2; - } - - UBRR0H = x >> 8; - UBRR0L = x; - - UCSR0B |= _BV(RXEN0); - UCSR0B |= _BV(RXCIE0); - UCSR0B |= _BV(TXEN0); - - UCSR0C |= _BV(USBS0); - UCSR0C |= _BV(UCSZ01) | _BV(UCSZ00); -} - -/* From the Arduino library */ -void delayMicroseconds(unsigned int us) { - if(--us == 0) - return; - - us <<= 2; - us -= 2; - - __asm__ __volatile__ ( - "1: sbiw %0,1" "\n\t" // 2 cycles - "brne 1b" : "=w" (us) : "0" (us) // 2 cycles - ); -} - -uint8_t getByte(void) { - /* Wait for data to be buffer */ - while(!(UCSR0A & (1 << RXC0))); - return (uint8_t)UDR0; -} - -void putByte(unsigned char data) { - /* Wait for empty transmit buffer */ - while(!(UCSR0A & (1 << UDRE0))); - UDR0 = (unsigned char) data; -} - -/*! \brief Writes an ASCII string to the TX buffer */ -void writeString(char *line) { - while(*line != '\0') { - putByte(*line); - ++line; - } -} - -char *readString(void) { - static char rxstr[32]; - static char *temp; - temp = rxstr; - - while((*temp = getByte()) != '\n') { - ++temp; - } - - return rxstr; -} - -void setup() { - uint8_t oldSREG = SREG; - - cli(); - - /* We initialize our array to zero - * here to spare resources while - * running. - */ - for(r=0;r 0) { - z = strlen(&data[sstart]); - s = sstart; - x = 0; - for(i = sstart; i < sstart + z; i++) { - if(data[i] == ',') { - data[i] = '\0'; - if(x == 0) { - minrawlen = atol(&data[s]); - } - if(x == 1) { - maxrawlen = atol(&data[s]); - } - if(x == 2) { - mingaplen = atoi(&data[s])/10; - } - x++; - s = i+1; - } - } - if(x == 3) { - maxgaplen = atol(&data[s])/10; - } - /* - * Once we tuned our firmware send back our settings + fw version - */ - sprintf(data, "v:%lu,%lu,%lu,%lu,%d,%d,%d@", minrawlen, maxrawlen, mingaplen*10, maxgaplen*10, VERSION, MIN_PULSELENGTH, MAX_PULSELENGTH); - writeString(data); - } else if(scode > 0 && spulse > 0 && srepeat > 0) { - z = strlen(&data[spulse]); - s = spulse; - nrpulses = 0; - for(i = spulse; i < spulse + z; i++) { - if(data[i] == ',') { - data[i] = '\0'; - plstypes[nrpulses++] = atoi(&data[s]); - s = i+1; - } - } - plstypes[nrpulses++] = atoi(&data[s]); - - codelen = strlen(&data[scode]); - repeats = atoi(&data[srepeat]); - cli(); - for(i=0;i 100000) { - putByte('\n'); - ten_us_counter1 = 0; - } - sei(); -} - -void broadcast() { - int i = 0, x = 0, match = 0, p = 0; - - putByte('c'); - putByte(':'); - for(i=0;i MIN_PULSELENGTH) { - if(ten_us_counter < MAX_PULSELENGTH) { - /* All codes are buffered */ - codes[nrpulses++] = ten_us_counter; - if(nrpulses > BUFFER_SIZE) { - nrpulses = 0; - } - /* Let's match footers */ - if(ten_us_counter > mingaplen) { - /* Only match minimal length pulse streams */ - if(nrpulses >= minrawlen && nrpulses <= maxrawlen) { - /* - * Sending pulses over serial requires - * a lot of cpu ticks. We therefor have - * to be sure that we send valid codes. - * Therefor, only streams we at least - * received twice communicated. - */ - if(rawlen == nrpulses) { - broadcast(); - } - rawlen = nrpulses; - } - nrpulses = 0; - } - } - } - ten_us_counter = 0; - TCNT1 = 0; - sei(); -} - -int main(void) { - setup(); - while(1); -}