From 2c61580157a6928b33c31f15e61d2930413da694 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <67171972+IoTManagerProject@users.noreply.github.com> Date: Thu, 1 Dec 2022 01:27:54 +0100 Subject: [PATCH] =?UTF-8?q?=D1=83=D0=B4=D0=B0=D0=BB=D1=8F=D0=B5=D0=BC=20?= =?UTF-8?q?=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE=D1=82=D0=B5=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MySensors => include}/MySensorsData.h | 0 lib/MySensors/.clang_complete | 3 - lib/MySensors/.editorconfig | 19 - lib/MySensors/.gitattributes | 22 - lib/MySensors/.github/FUNDING.yml | 1 - lib/MySensors/.gitignore | 15 - lib/MySensors/.piopm | 1 - lib/MySensors/.project | 11 - lib/MySensors/CONTRIBUTING.md | 1 - lib/MySensors/Logparser/logparser.css | 60 - lib/MySensors/Logparser/logparser.html | 38 - lib/MySensors/Logparser/logparser.js | 579 ---- lib/MySensors/Makefile | 154 -- lib/MySensors/MyASM.S | 39 - lib/MySensors/MyConfig.h | 2369 ----------------- lib/MySensors/MySensors.h | 456 ---- lib/MySensors/README.md | 19 - lib/MySensors/core/MyCapabilities.h | 244 -- lib/MySensors/core/MyEepromAddresses.h | 92 - lib/MySensors/core/MyGatewayTransport.cpp | 69 - lib/MySensors/core/MyGatewayTransport.h | 121 - .../core/MyGatewayTransportEthernet.cpp | 495 ---- .../core/MyGatewayTransportMQTTClient.cpp | 298 --- .../core/MyGatewayTransportSerial.cpp | 82 - lib/MySensors/core/MyHelperFunctions.cpp | 41 - lib/MySensors/core/MyHelperFunctions.h | 38 - lib/MySensors/core/MyInclusionMode.cpp | 72 - lib/MySensors/core/MyInclusionMode.h | 33 - lib/MySensors/core/MyIndication.cpp | 52 - lib/MySensors/core/MyIndication.h | 80 - lib/MySensors/core/MyLeds.cpp | 119 - lib/MySensors/core/MyLeds.h | 59 - lib/MySensors/core/MyMessage.cpp | 462 ---- lib/MySensors/core/MyMessage.h | 671 ----- lib/MySensors/core/MyOTAFirmwareUpdate.cpp | 287 -- lib/MySensors/core/MyOTAFirmwareUpdate.h | 200 -- lib/MySensors/core/MyOTALogging.cpp | 158 -- lib/MySensors/core/MyOTALogging.h | 73 - lib/MySensors/core/MyPrivateConfig.h.sample | 61 - lib/MySensors/core/MyProtocol.cpp | 167 -- lib/MySensors/core/MyProtocol.h | 33 - lib/MySensors/core/MySensorsCore.cpp | 833 ------ lib/MySensors/core/MySensorsCore.h | 509 ---- lib/MySensors/core/MySigning.cpp | 587 ---- lib/MySensors/core/MySigning.h | 907 ------- lib/MySensors/core/MySigningAtsha204.cpp | 357 --- lib/MySensors/core/MySigningAtsha204Soft.cpp | 374 --- lib/MySensors/core/MySplashScreen.cpp | 52 - lib/MySensors/core/MySplashScreen.h | 28 - lib/MySensors/core/MyTransport.cpp | 1173 -------- lib/MySensors/core/MyTransport.h | 573 ---- lib/MySensors/core/Version.h | 65 - lib/MySensors/drivers/ATSHA204/ATSHA204.cpp | 594 ----- lib/MySensors/drivers/ATSHA204/ATSHA204.h | 253 -- .../drivers/AltSoftSerial/AltSoftSerial.cpp | 377 --- .../drivers/AltSoftSerial/AltSoftSerial.h | 117 - lib/MySensors/drivers/AltSoftSerial/README.md | 9 - .../config/AltSoftSerial_Boards.h | 147 - .../config/AltSoftSerial_Timers.h | 187 -- .../AltSoftSerial/docs/issue_template.md | 64 - .../AltSoftSerial/examples/Echo/Echo.ino | 40 - .../examples/ReceiveTest/ReceiveTest.ino | 56 - .../ShowConfiguration/ShowConfiguration.ino | 97 - .../drivers/AltSoftSerial/keywords.txt | 4 - .../drivers/CircularBuffer/CircularBuffer.h | 197 -- lib/MySensors/drivers/I2CEeprom/I2CEeprom.cpp | 81 - lib/MySensors/drivers/I2CEeprom/I2CEeprom.h | 116 - lib/MySensors/drivers/NVM/Flash.h | 178 -- lib/MySensors/drivers/NVM/NVRAM.cpp | 342 --- lib/MySensors/drivers/NVM/NVRAM.h | 113 - lib/MySensors/drivers/NVM/README.md | 51 - lib/MySensors/drivers/NVM/VirtualPage.cpp | 349 --- lib/MySensors/drivers/NVM/VirtualPage.h | 139 - .../drivers/PubSubClient/CHANGES.txt | 76 - .../drivers/PubSubClient/LICENSE.txt | 20 - .../drivers/PubSubClient/PubSubClient.cpp | 736 ----- .../drivers/PubSubClient/PubSubClient.h | 183 -- lib/MySensors/drivers/PubSubClient/README.md | 48 - lib/MySensors/drivers/SPIFlash/License.txt | 674 ----- lib/MySensors/drivers/SPIFlash/README.md | 32 - lib/MySensors/drivers/SPIFlash/SPIFlash.cpp | 375 --- lib/MySensors/drivers/SPIFlash/SPIFlash.h | 198 -- .../SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino | 127 - lib/MySensors/drivers/SPIFlash/keywords.txt | 18 - lib/MySensors/drivers/TinyGSM/LICENSE | 165 -- lib/MySensors/drivers/TinyGSM/TinyGsmClient.h | 67 - .../drivers/TinyGSM/TinyGsmClientA6.h | 843 ------ .../drivers/TinyGSM/TinyGsmClientESP8266.h | 591 ---- .../drivers/TinyGSM/TinyGsmClientM590.h | 781 ------ .../drivers/TinyGSM/TinyGsmClientSIM800.h | 1057 -------- .../drivers/TinyGSM/TinyGsmClientSIM808.h | 163 -- .../drivers/TinyGSM/TinyGsmClientU201.h | 789 ------ .../drivers/TinyGSM/TinyGsmClientXBee.h | 752 ------ lib/MySensors/drivers/TinyGSM/TinyGsmCommon.h | 195 -- lib/MySensors/drivers/TinyGSM/TinyGsmFifo.h | 152 -- lib/MySensors/drivers/TinyGSM/keywords.txt | 26 - lib/MySensors/drivers/extEEPROM/LICENSE.md | 8 - lib/MySensors/drivers/extEEPROM/ReadMe.md | 226 -- .../eepromReadWrite/eepromReadWrite.ino | 209 -- .../examples/eepromTest/eepromTest.ino | 176 -- .../eepromTest_Wire1/eepromTest_Wire1.ino | 233 -- lib/MySensors/drivers/extEEPROM/extEEPROM.cpp | 257 -- lib/MySensors/drivers/extEEPROM/extEEPROM.h | 131 - lib/MySensors/drivers/extEEPROM/keywords.txt | 6 - .../AirQualitySensor/AirQualitySensor.ino | 219 -- .../BatteryPoweredSensor.ino | 95 - .../BinarySwitchSleepSensor.ino | 119 - .../examples/CO2Sensor/CO2Sensor.ino | 107 - .../ClearEepromConfig/ClearEepromConfig.ino | 44 - .../DimmableLEDActuator.ino | 130 - .../examples/DimmableLight/DimmableLight.ino | 158 -- .../examples/DustSensor/DustSensor.ino | 104 - .../examples/DustSensorDSM/DustSensorDSM.ino | 151 -- .../EnergyMeterPulseSensor.ino | 169 -- .../examples/GatewayESP32/GatewayESP32.ino | 84 - .../GatewayESP32MQTTClient.ino | 90 - .../GatewayESP32OTA/GatewayESP32OTA.ino | 120 - .../GatewayESP8266/GatewayESP8266.ino | 130 - .../GatewayESP8266MQTTClient.ino | 129 - .../GatewayESP8266OTA/GatewayESP8266OTA.ino | 156 -- .../GatewayGSMMQTTClient.ino | 137 - .../examples/GatewaySerial/GatewaySerial.ino | 101 - .../GatewaySerialRS485/GatewaySerialRS485.ino | 104 - .../examples/GatewayW5100/GatewayW5100.ino | 142 - .../GatewayW5100MQTTClient.ino | 154 -- .../examples/LightSensor/LightSensor.ino | 70 - .../examples/LogOTAGateway/LogOTAGateway.ino | 107 - .../examples/LogOTANode/LogOTANode.ino | 74 - .../examples/MockMySensors/MockMySensors.ino | 1515 ----------- .../examples/MockMySensors/README.md | 40 - .../examples/MotionSensor/MotionSensor.ino | 74 - .../MotionSensorRS485/MotionSensorRS485.ino | 98 - .../examples/Node2Node/Node2Node.ino | 76 - lib/MySensors/examples/PHSensor/PHSensor.ino | 85 - .../examples/PassiveNode/PassiveNode.ino | 69 - .../examples/PingPongSensor/MYSLog.h | 65 - .../PingPongSensor/PingPongSensor.ino | 127 - .../RFM69_RFM95_ATC_SignalReport.ino | 99 - .../examples/RelayActuator/RelayActuator.ino | 97 - .../examples/RepeaterNode/RepeaterNode.ino | 59 - .../SecretKnockSensor/SecretKnockSensor.ino | 409 --- .../SecureActuator/SecureActuator.ino | 128 - .../SecurityPersonalizer.ino | 1872 ------------- .../sha204_lib_return_codes.h | 45 - .../SecurityPersonalizer/sha204_library.cpp | 861 ------ .../SecurityPersonalizer/sha204_library.h | 467 ---- .../SensebenderGatewaySerial.ino | 281 -- .../SoilMoistSensor/SoilMoistSensor.ino | 198 -- lib/MySensors/examples/UVSensor/UVSensor.ino | 111 - .../VibrationSensor/VibrationSensor.ino | 101 - .../WaterMeterPulseSensor.ino | 194 -- .../hal/architecture/AVR/MyHwAVR.cpp | 370 --- lib/MySensors/hal/architecture/AVR/MyHwAVR.h | 92 - .../hal/architecture/AVR/MyMainAVR.cpp | 39 - .../AVR/drivers/DigitalIO/DigitalIO.h | 36 - .../AVR/drivers/DigitalIO/DigitalPin.h | 416 --- .../AVR/drivers/DigitalIO/I2cConstants.h | 62 - .../AVR/drivers/DigitalIO/PinIO.cpp | 75 - .../AVR/drivers/DigitalIO/PinIO.h | 194 -- .../AVR/drivers/DigitalIO/SoftI2cMaster.cpp | 252 -- .../AVR/drivers/DigitalIO/SoftI2cMaster.h | 314 --- .../AVR/drivers/DigitalIO/SoftSPI.h | 180 -- .../boards/AvrDevelopersGpioPinMap.h | 37 - .../DigitalIO/boards/BobuinoGpioPinMap.h | 37 - .../AVR/drivers/DigitalIO/boards/GpioPinMap.h | 64 - .../DigitalIO/boards/LeonardoGpioPinMap.h | 35 - .../drivers/DigitalIO/boards/MegaGpioPinMap.h | 75 - .../boards/SleepingBeautyGpioPinMap.h | 37 - .../DigitalIO/boards/Standard1284GpioPinMap.h | 37 - .../DigitalIO/boards/Teensy2GpioPinMap.h | 30 - .../DigitalIO/boards/Teensy2ppGpioPinMap.h | 51 - .../drivers/DigitalIO/boards/UnoGpioPinMap.h | 25 - .../DigitalWriteFast/digitalWriteFast.h | 31 - .../hal/architecture/ESP32/MyHwESP32.cpp | 144 - .../hal/architecture/ESP32/MyHwESP32.h | 107 - .../hal/architecture/ESP32/MyMainESP32.cpp | 57 - .../hal/architecture/ESP8266/MyHwESP8266.cpp | 156 -- .../hal/architecture/ESP8266/MyHwESP8266.h | 82 - .../architecture/ESP8266/MyMainESP8266.cpp | 348 --- .../architecture/Linux/MyHwLinuxGeneric.cpp | 165 -- .../hal/architecture/Linux/MyHwLinuxGeneric.h | 116 - .../architecture/Linux/MyMainLinuxGeneric.cpp | 488 ---- .../architecture/Linux/drivers/BCM/BCM.cpp | 80 - .../hal/architecture/Linux/drivers/BCM/BCM.h | 92 - .../architecture/Linux/drivers/BCM/RPi.cpp | 167 -- .../hal/architecture/Linux/drivers/BCM/RPi.h | 82 - .../architecture/Linux/drivers/BCM/SPIBCM.cpp | 110 - .../architecture/Linux/drivers/BCM/SPIBCM.h | 262 -- .../architecture/Linux/drivers/BCM/Wire.cpp | 213 -- .../hal/architecture/Linux/drivers/BCM/Wire.h | 94 - .../architecture/Linux/drivers/BCM/bcm2835.c | 1948 -------------- .../architecture/Linux/drivers/BCM/bcm2835.h | 1951 -------------- .../architecture/Linux/drivers/core/Arduino.h | 115 - .../architecture/Linux/drivers/core/Client.h | 54 - .../Linux/drivers/core/EthernetClient.cpp | 311 --- .../Linux/drivers/core/EthernetClient.h | 211 -- .../Linux/drivers/core/EthernetServer.cpp | 211 -- .../Linux/drivers/core/EthernetServer.h | 121 - .../architecture/Linux/drivers/core/GPIO.cpp | 211 -- .../architecture/Linux/drivers/core/GPIO.h | 91 - .../Linux/drivers/core/IPAddress.cpp | 110 - .../Linux/drivers/core/IPAddress.h | 165 -- .../architecture/Linux/drivers/core/Print.cpp | 272 -- .../architecture/Linux/drivers/core/Print.h | 98 - .../hal/architecture/Linux/drivers/core/SPI.h | 31 - .../Linux/drivers/core/SPIDEV.cpp | 368 --- .../architecture/Linux/drivers/core/SPIDEV.h | 212 -- .../Linux/drivers/core/SerialPort.cpp | 285 -- .../Linux/drivers/core/SerialPort.h | 114 - .../architecture/Linux/drivers/core/Server.h | 33 - .../Linux/drivers/core/SoftEeprom.cpp | 181 -- .../Linux/drivers/core/SoftEeprom.h | 104 - .../Linux/drivers/core/StdInOutStream.cpp | 56 - .../Linux/drivers/core/StdInOutStream.h | 76 - .../Linux/drivers/core/Stream.cpp | 292 -- .../architecture/Linux/drivers/core/Stream.h | 138 - .../Linux/drivers/core/compatibility.cpp | 96 - .../architecture/Linux/drivers/core/config.c | 304 --- .../architecture/Linux/drivers/core/config.h | 48 - .../Linux/drivers/core/interrupt.cpp | 252 -- .../Linux/drivers/core/interrupt.h | 45 - .../hal/architecture/Linux/drivers/core/log.c | 278 -- .../hal/architecture/Linux/drivers/core/log.h | 59 - .../Linux/drivers/core/noniso.cpp | 158 -- .../Linux/drivers/core/stdlib_noniso.h | 52 - lib/MySensors/hal/architecture/MyHwHAL.cpp | 71 - lib/MySensors/hal/architecture/MyHwHAL.h | 187 -- .../hal/architecture/NRF5/MyHwNRF5.cpp | 533 ---- .../hal/architecture/NRF5/MyHwNRF5.h | 208 -- .../hal/architecture/NRF5/MyMainNRF5.cpp | 39 - .../hal/architecture/NRF5/drivers/Flash.cpp | 165 -- .../NRF5/drivers/nrf5_wiring_constants.h | 42 - .../NRF5/drivers/nrf5_wiring_digital.c | 102 - .../hal/architecture/NRF5/drivers/nrf_temp.h | 70 - .../hal/architecture/NRF5/drivers/wdt.h | 186 -- .../hal/architecture/SAMD/MyHwSAMD.cpp | 256 -- .../hal/architecture/SAMD/MyHwSAMD.h | 144 - .../hal/architecture/SAMD/MyMainSAMD.cpp | 43 - .../hal/architecture/STM32F1/MyHwSTM32F1.cpp | 194 -- .../hal/architecture/STM32F1/MyHwSTM32F1.h | 93 - .../architecture/STM32F1/MyMainSTM32F1.cpp | 41 - .../hal/architecture/Teensy3/MyHwTeensy3.cpp | 174 -- .../hal/architecture/Teensy3/MyHwTeensy3.h | 91 - .../architecture/Teensy3/MyMainTeensy3.cpp | 31 - lib/MySensors/hal/crypto/AVR/MyCryptoAVR.cpp | 57 - lib/MySensors/hal/crypto/AVR/MyCryptoAVR.h | 29 - .../hal/crypto/AVR/drivers/AES/aes.cpp | 577 ---- .../hal/crypto/AVR/drivers/AES/aes.h | 111 - .../AVR/drivers/HMAC_SHA256/hmac_sha256.cpp | 61 - .../AVR/drivers/HMAC_SHA256/hmac_sha256.h | 78 - .../hal/crypto/AVR/drivers/SHA256/SHA256.S | 1038 -------- .../hal/crypto/AVR/drivers/SHA256/sha256.cpp | 46 - .../hal/crypto/AVR/drivers/SHA256/sha256.h | 128 - .../hal/crypto/ESP32/MyCryptoESP32.cpp | 66 - .../hal/crypto/ESP32/MyCryptoESP32.h | 27 - lib/MySensors/hal/crypto/MyCryptoHAL.h | 68 - .../hal/crypto/generic/MyCryptoGeneric.cpp | 45 - .../hal/crypto/generic/MyCryptoGeneric.h | 28 - .../hal/crypto/generic/drivers/AES/AES.cpp | 631 ----- .../hal/crypto/generic/drivers/AES/AES.h | 381 --- .../crypto/generic/drivers/AES/AES_config.h | 50 - .../hal/crypto/generic/drivers/AES/README.MD | 91 - .../crypto/generic/drivers/AES/keywords.txt | 7 - .../drivers/HMAC_SHA256/hmac_sha256.cpp | 64 - .../generic/drivers/HMAC_SHA256/hmac_sha256.h | 28 - .../crypto/generic/drivers/SHA256/sha256.cpp | 173 -- .../crypto/generic/drivers/SHA256/sha256.h | 43 - .../hal/transport/MyTransportHAL.cpp | 241 -- lib/MySensors/hal/transport/MyTransportHAL.h | 176 -- .../NRF5_ESB/MyTransportNRF5_ESB.cpp | 118 - .../hal/transport/NRF5_ESB/driver/Radio.cpp | 90 - .../hal/transport/NRF5_ESB/driver/Radio.h | 77 - .../transport/NRF5_ESB/driver/Radio_ESB.cpp | 710 ----- .../hal/transport/NRF5_ESB/driver/Radio_ESB.h | 174 -- .../hal/transport/RF24/MyTransportRF24.cpp | 166 -- .../hal/transport/RF24/driver/RF24.cpp | 577 ---- .../hal/transport/RF24/driver/RF24.h | 407 --- .../hal/transport/RF24/driver/RF24registers.h | 159 -- .../hal/transport/RFM69/MyTransportRFM69.cpp | 301 --- .../transport/RFM69/driver/new/RFM69_new.cpp | 1037 -------- .../transport/RFM69/driver/new/RFM69_new.h | 561 ---- .../RFM69/driver/new/RFM69registers_new.h | 984 ------- .../transport/RFM69/driver/old/RFM69_old.cpp | 913 ------- .../transport/RFM69/driver/old/RFM69_old.h | 232 -- .../RFM69/driver/old/RFM69registers_old.h | 1109 -------- .../hal/transport/RFM95/MyTransportRFM95.cpp | 126 - .../hal/transport/RFM95/driver/RFM95.cpp | 685 ----- .../hal/transport/RFM95/driver/RFM95.h | 487 ---- .../transport/RFM95/driver/RFM95registers.h | 205 -- .../hal/transport/RS485/MyTransportRS485.cpp | 443 --- lib/MySensors/keywords.txt | 376 --- lib/MySensors/library.json | 26 - lib/MySensors/library.properties | 9 - .../exec/MySensors => }/MySensorsData.cpp | 0 src/modules/exec/MySensors/modinfo.json | 4 +- 295 files changed, 3 insertions(+), 67232 deletions(-) rename {src/modules/exec/MySensors => include}/MySensorsData.h (100%) delete mode 100644 lib/MySensors/.clang_complete delete mode 100644 lib/MySensors/.editorconfig delete mode 100644 lib/MySensors/.gitattributes delete mode 100644 lib/MySensors/.github/FUNDING.yml delete mode 100644 lib/MySensors/.gitignore delete mode 100644 lib/MySensors/.piopm delete mode 100644 lib/MySensors/.project delete mode 100644 lib/MySensors/CONTRIBUTING.md delete mode 100644 lib/MySensors/Logparser/logparser.css delete mode 100644 lib/MySensors/Logparser/logparser.html delete mode 100644 lib/MySensors/Logparser/logparser.js delete mode 100644 lib/MySensors/Makefile delete mode 100644 lib/MySensors/MyASM.S delete mode 100644 lib/MySensors/MyConfig.h delete mode 100644 lib/MySensors/MySensors.h delete mode 100644 lib/MySensors/README.md delete mode 100644 lib/MySensors/core/MyCapabilities.h delete mode 100644 lib/MySensors/core/MyEepromAddresses.h delete mode 100644 lib/MySensors/core/MyGatewayTransport.cpp delete mode 100644 lib/MySensors/core/MyGatewayTransport.h delete mode 100644 lib/MySensors/core/MyGatewayTransportEthernet.cpp delete mode 100644 lib/MySensors/core/MyGatewayTransportMQTTClient.cpp delete mode 100644 lib/MySensors/core/MyGatewayTransportSerial.cpp delete mode 100644 lib/MySensors/core/MyHelperFunctions.cpp delete mode 100644 lib/MySensors/core/MyHelperFunctions.h delete mode 100644 lib/MySensors/core/MyInclusionMode.cpp delete mode 100644 lib/MySensors/core/MyInclusionMode.h delete mode 100644 lib/MySensors/core/MyIndication.cpp delete mode 100644 lib/MySensors/core/MyIndication.h delete mode 100644 lib/MySensors/core/MyLeds.cpp delete mode 100644 lib/MySensors/core/MyLeds.h delete mode 100644 lib/MySensors/core/MyMessage.cpp delete mode 100644 lib/MySensors/core/MyMessage.h delete mode 100644 lib/MySensors/core/MyOTAFirmwareUpdate.cpp delete mode 100644 lib/MySensors/core/MyOTAFirmwareUpdate.h delete mode 100644 lib/MySensors/core/MyOTALogging.cpp delete mode 100644 lib/MySensors/core/MyOTALogging.h delete mode 100644 lib/MySensors/core/MyPrivateConfig.h.sample delete mode 100644 lib/MySensors/core/MyProtocol.cpp delete mode 100644 lib/MySensors/core/MyProtocol.h delete mode 100644 lib/MySensors/core/MySensorsCore.cpp delete mode 100644 lib/MySensors/core/MySensorsCore.h delete mode 100644 lib/MySensors/core/MySigning.cpp delete mode 100644 lib/MySensors/core/MySigning.h delete mode 100644 lib/MySensors/core/MySigningAtsha204.cpp delete mode 100644 lib/MySensors/core/MySigningAtsha204Soft.cpp delete mode 100644 lib/MySensors/core/MySplashScreen.cpp delete mode 100644 lib/MySensors/core/MySplashScreen.h delete mode 100644 lib/MySensors/core/MyTransport.cpp delete mode 100644 lib/MySensors/core/MyTransport.h delete mode 100644 lib/MySensors/core/Version.h delete mode 100644 lib/MySensors/drivers/ATSHA204/ATSHA204.cpp delete mode 100644 lib/MySensors/drivers/ATSHA204/ATSHA204.h delete mode 100644 lib/MySensors/drivers/AltSoftSerial/AltSoftSerial.cpp delete mode 100644 lib/MySensors/drivers/AltSoftSerial/AltSoftSerial.h delete mode 100644 lib/MySensors/drivers/AltSoftSerial/README.md delete mode 100644 lib/MySensors/drivers/AltSoftSerial/config/AltSoftSerial_Boards.h delete mode 100644 lib/MySensors/drivers/AltSoftSerial/config/AltSoftSerial_Timers.h delete mode 100644 lib/MySensors/drivers/AltSoftSerial/docs/issue_template.md delete mode 100644 lib/MySensors/drivers/AltSoftSerial/examples/Echo/Echo.ino delete mode 100644 lib/MySensors/drivers/AltSoftSerial/examples/ReceiveTest/ReceiveTest.ino delete mode 100644 lib/MySensors/drivers/AltSoftSerial/examples/ShowConfiguration/ShowConfiguration.ino delete mode 100644 lib/MySensors/drivers/AltSoftSerial/keywords.txt delete mode 100644 lib/MySensors/drivers/CircularBuffer/CircularBuffer.h delete mode 100644 lib/MySensors/drivers/I2CEeprom/I2CEeprom.cpp delete mode 100644 lib/MySensors/drivers/I2CEeprom/I2CEeprom.h delete mode 100644 lib/MySensors/drivers/NVM/Flash.h delete mode 100644 lib/MySensors/drivers/NVM/NVRAM.cpp delete mode 100644 lib/MySensors/drivers/NVM/NVRAM.h delete mode 100644 lib/MySensors/drivers/NVM/README.md delete mode 100644 lib/MySensors/drivers/NVM/VirtualPage.cpp delete mode 100644 lib/MySensors/drivers/NVM/VirtualPage.h delete mode 100644 lib/MySensors/drivers/PubSubClient/CHANGES.txt delete mode 100644 lib/MySensors/drivers/PubSubClient/LICENSE.txt delete mode 100644 lib/MySensors/drivers/PubSubClient/PubSubClient.cpp delete mode 100644 lib/MySensors/drivers/PubSubClient/PubSubClient.h delete mode 100644 lib/MySensors/drivers/PubSubClient/README.md delete mode 100644 lib/MySensors/drivers/SPIFlash/License.txt delete mode 100644 lib/MySensors/drivers/SPIFlash/README.md delete mode 100644 lib/MySensors/drivers/SPIFlash/SPIFlash.cpp delete mode 100644 lib/MySensors/drivers/SPIFlash/SPIFlash.h delete mode 100644 lib/MySensors/drivers/SPIFlash/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino delete mode 100644 lib/MySensors/drivers/SPIFlash/keywords.txt delete mode 100644 lib/MySensors/drivers/TinyGSM/LICENSE delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmClient.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmClientA6.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmClientESP8266.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmClientM590.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmClientSIM800.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmClientSIM808.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmClientU201.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmClientXBee.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmCommon.h delete mode 100644 lib/MySensors/drivers/TinyGSM/TinyGsmFifo.h delete mode 100644 lib/MySensors/drivers/TinyGSM/keywords.txt delete mode 100644 lib/MySensors/drivers/extEEPROM/LICENSE.md delete mode 100644 lib/MySensors/drivers/extEEPROM/ReadMe.md delete mode 100644 lib/MySensors/drivers/extEEPROM/examples/eepromReadWrite/eepromReadWrite.ino delete mode 100644 lib/MySensors/drivers/extEEPROM/examples/eepromTest/eepromTest.ino delete mode 100644 lib/MySensors/drivers/extEEPROM/examples/eepromTest_Wire1/eepromTest_Wire1.ino delete mode 100644 lib/MySensors/drivers/extEEPROM/extEEPROM.cpp delete mode 100644 lib/MySensors/drivers/extEEPROM/extEEPROM.h delete mode 100644 lib/MySensors/drivers/extEEPROM/keywords.txt delete mode 100644 lib/MySensors/examples/AirQualitySensor/AirQualitySensor.ino delete mode 100644 lib/MySensors/examples/BatteryPoweredSensor/BatteryPoweredSensor.ino delete mode 100644 lib/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino delete mode 100644 lib/MySensors/examples/CO2Sensor/CO2Sensor.ino delete mode 100644 lib/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino delete mode 100644 lib/MySensors/examples/DimmableLEDActuator/DimmableLEDActuator.ino delete mode 100644 lib/MySensors/examples/DimmableLight/DimmableLight.ino delete mode 100644 lib/MySensors/examples/DustSensor/DustSensor.ino delete mode 100644 lib/MySensors/examples/DustSensorDSM/DustSensorDSM.ino delete mode 100644 lib/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino delete mode 100644 lib/MySensors/examples/GatewayESP32/GatewayESP32.ino delete mode 100644 lib/MySensors/examples/GatewayESP32MQTTClient/GatewayESP32MQTTClient.ino delete mode 100644 lib/MySensors/examples/GatewayESP32OTA/GatewayESP32OTA.ino delete mode 100644 lib/MySensors/examples/GatewayESP8266/GatewayESP8266.ino delete mode 100644 lib/MySensors/examples/GatewayESP8266MQTTClient/GatewayESP8266MQTTClient.ino delete mode 100644 lib/MySensors/examples/GatewayESP8266OTA/GatewayESP8266OTA.ino delete mode 100644 lib/MySensors/examples/GatewayGSMMQTTClient/GatewayGSMMQTTClient.ino delete mode 100644 lib/MySensors/examples/GatewaySerial/GatewaySerial.ino delete mode 100644 lib/MySensors/examples/GatewaySerialRS485/GatewaySerialRS485.ino delete mode 100644 lib/MySensors/examples/GatewayW5100/GatewayW5100.ino delete mode 100644 lib/MySensors/examples/GatewayW5100MQTTClient/GatewayW5100MQTTClient.ino delete mode 100644 lib/MySensors/examples/LightSensor/LightSensor.ino delete mode 100644 lib/MySensors/examples/LogOTAGateway/LogOTAGateway.ino delete mode 100644 lib/MySensors/examples/LogOTANode/LogOTANode.ino delete mode 100644 lib/MySensors/examples/MockMySensors/MockMySensors.ino delete mode 100644 lib/MySensors/examples/MockMySensors/README.md delete mode 100644 lib/MySensors/examples/MotionSensor/MotionSensor.ino delete mode 100644 lib/MySensors/examples/MotionSensorRS485/MotionSensorRS485.ino delete mode 100644 lib/MySensors/examples/Node2Node/Node2Node.ino delete mode 100644 lib/MySensors/examples/PHSensor/PHSensor.ino delete mode 100644 lib/MySensors/examples/PassiveNode/PassiveNode.ino delete mode 100644 lib/MySensors/examples/PingPongSensor/MYSLog.h delete mode 100644 lib/MySensors/examples/PingPongSensor/PingPongSensor.ino delete mode 100644 lib/MySensors/examples/RFM69_RFM95_ATC_SignalReport/RFM69_RFM95_ATC_SignalReport.ino delete mode 100644 lib/MySensors/examples/RelayActuator/RelayActuator.ino delete mode 100644 lib/MySensors/examples/RepeaterNode/RepeaterNode.ino delete mode 100644 lib/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino delete mode 100644 lib/MySensors/examples/SecureActuator/SecureActuator.ino delete mode 100644 lib/MySensors/examples/SecurityPersonalizer/SecurityPersonalizer.ino delete mode 100644 lib/MySensors/examples/SecurityPersonalizer/sha204_lib_return_codes.h delete mode 100644 lib/MySensors/examples/SecurityPersonalizer/sha204_library.cpp delete mode 100644 lib/MySensors/examples/SecurityPersonalizer/sha204_library.h delete mode 100644 lib/MySensors/examples/SensebenderGatewaySerial/SensebenderGatewaySerial.ino delete mode 100644 lib/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino delete mode 100644 lib/MySensors/examples/UVSensor/UVSensor.ino delete mode 100644 lib/MySensors/examples/VibrationSensor/VibrationSensor.ino delete mode 100644 lib/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino delete mode 100644 lib/MySensors/hal/architecture/AVR/MyHwAVR.cpp delete mode 100644 lib/MySensors/hal/architecture/AVR/MyHwAVR.h delete mode 100644 lib/MySensors/hal/architecture/AVR/MyMainAVR.cpp delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/DigitalIO.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/DigitalPin.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/I2cConstants.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/PinIO.cpp delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/PinIO.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftI2cMaster.cpp delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftI2cMaster.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftSPI.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/AvrDevelopersGpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/BobuinoGpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/GpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/LeonardoGpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/MegaGpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/SleepingBeautyGpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Standard1284GpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Teensy2GpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Teensy2ppGpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/UnoGpioPinMap.h delete mode 100644 lib/MySensors/hal/architecture/AVR/drivers/DigitalWriteFast/digitalWriteFast.h delete mode 100644 lib/MySensors/hal/architecture/ESP32/MyHwESP32.cpp delete mode 100644 lib/MySensors/hal/architecture/ESP32/MyHwESP32.h delete mode 100644 lib/MySensors/hal/architecture/ESP32/MyMainESP32.cpp delete mode 100644 lib/MySensors/hal/architecture/ESP8266/MyHwESP8266.cpp delete mode 100644 lib/MySensors/hal/architecture/ESP8266/MyHwESP8266.h delete mode 100644 lib/MySensors/hal/architecture/ESP8266/MyMainESP8266.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/MyHwLinuxGeneric.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/MyHwLinuxGeneric.h delete mode 100644 lib/MySensors/hal/architecture/Linux/MyMainLinuxGeneric.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/BCM.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/BCM.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/RPi.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/RPi.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/SPIBCM.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/SPIBCM.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/Wire.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/Wire.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/bcm2835.c delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/BCM/bcm2835.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/Arduino.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/Client.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/EthernetClient.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/EthernetClient.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/EthernetServer.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/EthernetServer.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/GPIO.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/GPIO.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/IPAddress.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/IPAddress.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/Print.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/Print.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/SPI.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/SPIDEV.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/SPIDEV.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/SerialPort.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/SerialPort.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/Server.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/SoftEeprom.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/SoftEeprom.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/StdInOutStream.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/StdInOutStream.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/Stream.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/Stream.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/compatibility.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/config.c delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/config.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/interrupt.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/interrupt.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/log.c delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/log.h delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/noniso.cpp delete mode 100644 lib/MySensors/hal/architecture/Linux/drivers/core/stdlib_noniso.h delete mode 100644 lib/MySensors/hal/architecture/MyHwHAL.cpp delete mode 100644 lib/MySensors/hal/architecture/MyHwHAL.h delete mode 100644 lib/MySensors/hal/architecture/NRF5/MyHwNRF5.cpp delete mode 100644 lib/MySensors/hal/architecture/NRF5/MyHwNRF5.h delete mode 100644 lib/MySensors/hal/architecture/NRF5/MyMainNRF5.cpp delete mode 100644 lib/MySensors/hal/architecture/NRF5/drivers/Flash.cpp delete mode 100644 lib/MySensors/hal/architecture/NRF5/drivers/nrf5_wiring_constants.h delete mode 100644 lib/MySensors/hal/architecture/NRF5/drivers/nrf5_wiring_digital.c delete mode 100644 lib/MySensors/hal/architecture/NRF5/drivers/nrf_temp.h delete mode 100644 lib/MySensors/hal/architecture/NRF5/drivers/wdt.h delete mode 100644 lib/MySensors/hal/architecture/SAMD/MyHwSAMD.cpp delete mode 100644 lib/MySensors/hal/architecture/SAMD/MyHwSAMD.h delete mode 100644 lib/MySensors/hal/architecture/SAMD/MyMainSAMD.cpp delete mode 100644 lib/MySensors/hal/architecture/STM32F1/MyHwSTM32F1.cpp delete mode 100644 lib/MySensors/hal/architecture/STM32F1/MyHwSTM32F1.h delete mode 100644 lib/MySensors/hal/architecture/STM32F1/MyMainSTM32F1.cpp delete mode 100644 lib/MySensors/hal/architecture/Teensy3/MyHwTeensy3.cpp delete mode 100644 lib/MySensors/hal/architecture/Teensy3/MyHwTeensy3.h delete mode 100644 lib/MySensors/hal/architecture/Teensy3/MyMainTeensy3.cpp delete mode 100644 lib/MySensors/hal/crypto/AVR/MyCryptoAVR.cpp delete mode 100644 lib/MySensors/hal/crypto/AVR/MyCryptoAVR.h delete mode 100644 lib/MySensors/hal/crypto/AVR/drivers/AES/aes.cpp delete mode 100644 lib/MySensors/hal/crypto/AVR/drivers/AES/aes.h delete mode 100644 lib/MySensors/hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.cpp delete mode 100644 lib/MySensors/hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.h delete mode 100644 lib/MySensors/hal/crypto/AVR/drivers/SHA256/SHA256.S delete mode 100644 lib/MySensors/hal/crypto/AVR/drivers/SHA256/sha256.cpp delete mode 100644 lib/MySensors/hal/crypto/AVR/drivers/SHA256/sha256.h delete mode 100644 lib/MySensors/hal/crypto/ESP32/MyCryptoESP32.cpp delete mode 100644 lib/MySensors/hal/crypto/ESP32/MyCryptoESP32.h delete mode 100644 lib/MySensors/hal/crypto/MyCryptoHAL.h delete mode 100644 lib/MySensors/hal/crypto/generic/MyCryptoGeneric.cpp delete mode 100644 lib/MySensors/hal/crypto/generic/MyCryptoGeneric.h delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/AES/AES.cpp delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/AES/AES.h delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/AES/AES_config.h delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/AES/README.MD delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/AES/keywords.txt delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.cpp delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.h delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/SHA256/sha256.cpp delete mode 100644 lib/MySensors/hal/crypto/generic/drivers/SHA256/sha256.h delete mode 100644 lib/MySensors/hal/transport/MyTransportHAL.cpp delete mode 100644 lib/MySensors/hal/transport/MyTransportHAL.h delete mode 100644 lib/MySensors/hal/transport/NRF5_ESB/MyTransportNRF5_ESB.cpp delete mode 100644 lib/MySensors/hal/transport/NRF5_ESB/driver/Radio.cpp delete mode 100644 lib/MySensors/hal/transport/NRF5_ESB/driver/Radio.h delete mode 100644 lib/MySensors/hal/transport/NRF5_ESB/driver/Radio_ESB.cpp delete mode 100644 lib/MySensors/hal/transport/NRF5_ESB/driver/Radio_ESB.h delete mode 100644 lib/MySensors/hal/transport/RF24/MyTransportRF24.cpp delete mode 100644 lib/MySensors/hal/transport/RF24/driver/RF24.cpp delete mode 100644 lib/MySensors/hal/transport/RF24/driver/RF24.h delete mode 100644 lib/MySensors/hal/transport/RF24/driver/RF24registers.h delete mode 100644 lib/MySensors/hal/transport/RFM69/MyTransportRFM69.cpp delete mode 100644 lib/MySensors/hal/transport/RFM69/driver/new/RFM69_new.cpp delete mode 100644 lib/MySensors/hal/transport/RFM69/driver/new/RFM69_new.h delete mode 100644 lib/MySensors/hal/transport/RFM69/driver/new/RFM69registers_new.h delete mode 100644 lib/MySensors/hal/transport/RFM69/driver/old/RFM69_old.cpp delete mode 100644 lib/MySensors/hal/transport/RFM69/driver/old/RFM69_old.h delete mode 100644 lib/MySensors/hal/transport/RFM69/driver/old/RFM69registers_old.h delete mode 100644 lib/MySensors/hal/transport/RFM95/MyTransportRFM95.cpp delete mode 100644 lib/MySensors/hal/transport/RFM95/driver/RFM95.cpp delete mode 100644 lib/MySensors/hal/transport/RFM95/driver/RFM95.h delete mode 100644 lib/MySensors/hal/transport/RFM95/driver/RFM95registers.h delete mode 100644 lib/MySensors/hal/transport/RS485/MyTransportRS485.cpp delete mode 100644 lib/MySensors/keywords.txt delete mode 100644 lib/MySensors/library.json delete mode 100644 lib/MySensors/library.properties rename src/{modules/exec/MySensors => }/MySensorsData.cpp (100%) diff --git a/src/modules/exec/MySensors/MySensorsData.h b/include/MySensorsData.h similarity index 100% rename from src/modules/exec/MySensors/MySensorsData.h rename to include/MySensorsData.h diff --git a/lib/MySensors/.clang_complete b/lib/MySensors/.clang_complete deleted file mode 100644 index e901cf38..00000000 --- a/lib/MySensors/.clang_complete +++ /dev/null @@ -1,3 +0,0 @@ --Idrivers\Linux --Idrivers\ATSHA204 --Icore diff --git a/lib/MySensors/.editorconfig b/lib/MySensors/.editorconfig deleted file mode 100644 index f74d4a18..00000000 --- a/lib/MySensors/.editorconfig +++ /dev/null @@ -1,19 +0,0 @@ -# EditorConfig is awesome: http://EditorConfig.org - -# top-most EditorConfig file -root = true - -# Unix-style newlines with UTF-8 encoding for every file -[*] -end_of_line = lf -charset = utf-8 - -# For all source code -[*.{c,cpp,h,ino,sh}] -insert_final_newline = true -indent_style = tab -indent_size = 2 - -# Tab indentation also for makefiles -[Makefile] -indent_style = tab diff --git a/lib/MySensors/.gitattributes b/lib/MySensors/.gitattributes deleted file mode 100644 index 8deb27c5..00000000 --- a/lib/MySensors/.gitattributes +++ /dev/null @@ -1,22 +0,0 @@ -# Set default behaviour, in case users don't have core.autocrlf set. -* text eol=lf - -# Explicitly declare text files we want to always be normalized and converted -# to native line endings on checkout. -*.c text -*.cpp text -*.h text -*.ino text -*.xml text -*.lua text - -# Denote all files that are truly binary and should not be modified. -*.png binary -*.jpg binary -*.gif binary -*.ttf binary -*.eot binary -*.svg binary -*.woff binary -*.epg binary -*.jar binary diff --git a/lib/MySensors/.github/FUNDING.yml b/lib/MySensors/.github/FUNDING.yml deleted file mode 100644 index 8fbde8c5..00000000 --- a/lib/MySensors/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -custom: https://www.mysensors.org/hall-of-fame diff --git a/lib/MySensors/.gitignore b/lib/MySensors/.gitignore deleted file mode 100644 index bec8ade2..00000000 --- a/lib/MySensors/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -stino.settings -*~ -*bak -MyPrivateConfig.h -Documentation/html -doxygen_sqlite3.db -Makefile.inc -build -bin -*.sublime-workspace -.idea -doxygen.log -TAGS -tags -.DS_Store diff --git a/lib/MySensors/.piopm b/lib/MySensors/.piopm deleted file mode 100644 index 7d28b5cc..00000000 --- a/lib/MySensors/.piopm +++ /dev/null @@ -1 +0,0 @@ -{"type": "library", "name": "MySensors", "version": "2.3.2", "spec": {"owner": "mysensors", "id": 548, "name": "MySensors", "requirements": null, "uri": null}} \ No newline at end of file diff --git a/lib/MySensors/.project b/lib/MySensors/.project deleted file mode 100644 index 2c5928fd..00000000 --- a/lib/MySensors/.project +++ /dev/null @@ -1,11 +0,0 @@ - - - MySensors-Arduino - - - - - - - - diff --git a/lib/MySensors/CONTRIBUTING.md b/lib/MySensors/CONTRIBUTING.md deleted file mode 100644 index 6e019193..00000000 --- a/lib/MySensors/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ -MySensors Code Contribution Guidelines diff --git a/lib/MySensors/Logparser/logparser.css b/lib/MySensors/Logparser/logparser.css deleted file mode 100644 index ff508f06..00000000 --- a/lib/MySensors/Logparser/logparser.css +++ /dev/null @@ -1,60 +0,0 @@ -@charset "UTF-8";/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:Glyphicons Halflings;src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:Glyphicons Halflings;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:transparent}body{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:16px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:22px;margin-bottom:22px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:22px;margin-bottom:11px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:11px;margin-bottom:11px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:41px}h2,.h2{font-size:34px}h3,.h3{font-size:28px}h4,.h4{font-size:20px}h5,.h5{font-size:16px}h6,.h6{font-size:14px}p{margin:0 0 11px}.lead{margin-bottom:22px;font-size:18px;font-weight:300;line-height:1.4}@media(min-width:768px){.lead{font-size:24px}}small,.small{font-size:87%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:10px;margin:44px 0 22px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:11px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:22px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media(min-width:100px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:11px 22px;margin:0 0 22px;font-size:20px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:22px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,Courier New,monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;box-shadow:none}pre{display:block;padding:10.5px;margin:0 0 11px;font-size:15px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media(min-width:768px){.container{width:750px}}@media(min-width:992px){.container{width:970px}}@media(min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media(min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:22px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:16.5px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:22px;font-size:24px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:16px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:36px;padding:6px 12px;font-size:16px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:36px;line-height:1.42857143 \0}input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:33px;line-height:1.5 \0}input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:49px;line-height:1.33 \0}_:-ms-fullscreen,:root input[type=date],:root input[type=time],:root input[type=datetime-local],:root input[type=month]{line-height:1.42857143}_:-ms-fullscreen.input-sm,:root input[type=date].input-sm,:root input[type=time].input-sm,:root input[type=datetime-local].input-sm,:root input[type=month].input-sm{line-height:1.5}_:-ms-fullscreen.input-lg,:root input[type=date].input-lg,:root input[type=time].input-lg,:root input[type=datetime-local].input-lg,:root input[type=month].input-lg{line-height:1.33}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:22px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],input[type=radio].disabled,input[type=checkbox].disabled,fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm,.form-group-sm .form-control{height:33px;padding:5px 10px;font-size:14px;line-height:1.5;border-radius:3px}select.input-sm,select.form-group-sm .form-control{height:33px;line-height:33px}textarea.input-sm,textarea.form-group-sm .form-control,select[multiple].input-sm,select[multiple].form-group-sm .form-control{height:auto}.input-lg,.form-group-lg .form-control{height:49px;padding:10px 16px;font-size:20px;line-height:1.33;border-radius:6px}select.input-lg,select.form-group-lg .form-control{height:49px;line-height:49px}textarea.input-lg,textarea.form-group-lg .form-control,select[multiple].input-lg,select[multiple].form-group-lg .form-control{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:45px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:36px;height:36px;line-height:36px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:49px;height:49px;line-height:49px}.input-sm+.form-control-feedback{width:33px;height:33px;line-height:33px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:27px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:29px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media(min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media(min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media(min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:16px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default.focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:hover,.btn-primary:focus,.btn-primary.focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success.focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info.focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning.focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger.focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:400;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:20px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:14px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:14px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:16px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:10px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:14px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:100px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:49px;padding:10px 16px;font-size:20px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:49px;line-height:49px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:33px;padding:5px 10px;font-size:14px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:33px;line-height:33px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:16px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:14px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:20px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:10px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:60px;margin-bottom:22px;border:1px solid transparent}@media(min-width:100px){.navbar{border-radius:4px}}@media(min-width:100px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media(min-width:100px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;visibility:visible!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media(max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:100px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media(min-width:100px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media(min-width:100px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:19px 15px;font-size:20px;line-height:22px;height:60px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media(min-width:100px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:13px;margin-bottom:13px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:100px){.navbar-toggle{display:none}}.navbar-nav{margin:9.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:22px}@media(max-width:99px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:22px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:100px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:19px;padding-bottom:19px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:12px;margin-bottom:12px}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media(max-width:99px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media(min-width:100px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:12px;margin-bottom:12px}.navbar-btn.btn-sm{margin-top:13.5px;margin-bottom:13.5px}.navbar-btn.btn-xs{margin-top:19px;margin-bottom:19px}.navbar-text{margin-top:19px;margin-bottom:19px}@media(min-width:100px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media(min-width:100px){.navbar-left{float:left}.navbar-right{float:right;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media(max-width:99px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media(max-width:99px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:22px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:22px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:20px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:14px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:22px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:14px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px 15px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:24px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:72px}}.thumbnail{display:block;padding:4px;margin-bottom:22px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:22px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:22px;margin-bottom:22px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:14px;line-height:22px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;color:#555;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:22px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:18px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:22px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:24px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media(min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media(min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;visibility:visible;font-size:14px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-size:16px;font-weight:400;line-height:1.42857143;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:16px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{transition:transform .6s ease-in-out;backface-visibility:hidden;perspective:1000}.carousel-inner>.item.next,.carousel-inner>.item.active.right{transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{transform:translate3d(0,0,0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:transparent}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(max-width:767px){.visible-xs-block{display:block!important}}@media(max-width:767px){.visible-xs-inline{display:inline!important}}@media(max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media(min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media(min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media(min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media(min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media(min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media(min-width:1200px){.visible-lg-block{display:block!important}}@media(min-width:1200px){.visible-lg-inline{display:inline!important}}@media(min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media(max-width:767px){.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}@keyframes popIn{0%{transform:scale(1,1)}25%{transform:scale(1.2,1)}50%{transform:scale(1.4,1)}100%{transform:scale(1,1)}}@keyframes popOut{0%{transform:scale(1,1)}25%{transform:scale(1.2,1)}50%{transform:scale(1.4,1)}100%{transform:scale(1,1)}}@keyframes splashIn{0%{transform:scale(1);opacity:1}25%{transform:scale(1.1);opacity:.8}50%{transform:scale(1.1);opacity:.9}100%{transform:scale(1);opacity:1}}@keyframes splashOut{0%{transform:scale(1);opacity:1}25%{transform:scale(1);opacity:.8}50%{transform:scale(1);opacity:.9}100%{transform:scale(.5);opacity:1}}.checkbox-toggle{position:relative}.checkbox-toggle input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-toggle input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-toggle input+span{cursor:pointer;user-select:none}.checkbox-toggle input+span:before{position:absolute;left:0;display:inline-block}.checkbox-toggle input+span>h4{display:inline}.form-horizontal [class^=checkbox] input+span:after{top:7px}.checkbox-slider{position:relative}.checkbox-slider input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-slider input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-slider input+span{cursor:pointer;user-select:none}.checkbox-slider input+span:before{position:absolute;left:0;display:inline-block}.checkbox-slider input+span>h4{display:inline}.checkbox-slider input+span{padding-left:40px}.checkbox-slider input+span:before{content:"";height:20px;width:40px;background:rgba(100,100,100,.2);box-shadow:inset 0 0 5px rgba(0,0,0,.8);transition:background .2s ease-out}.checkbox-slider input+span:after{width:20px;height:20px;position:absolute;left:0;top:0;display:block;background:#FFF;transition:margin-left .1s ease-in-out;text-align:center;font-weight:700;content:""}.checkbox-slider input:checked+span:after{margin-left:20px;content:""}.checkbox-slider input:checked+span:before{transition:background .2s ease-in}.checkbox-slider--default{position:relative}.checkbox-slider--default input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-slider--default input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-slider--default input+span{cursor:pointer;user-select:none}.checkbox-slider--default input+span:before{position:absolute;left:0;display:inline-block}.checkbox-slider--default input+span>h4{display:inline}.checkbox-slider--default input+span{padding-left:40px}.checkbox-slider--default input+span:before{content:"";height:20px;width:40px;background:rgba(100,100,100,.2);box-shadow:inset 0 0 5px rgba(0,0,0,.8);transition:background .2s ease-out}.checkbox-slider--default input+span:after{width:20px;height:20px;position:absolute;left:0;top:0;display:block;background:#FFF;transition:margin-left .1s ease-in-out;text-align:center;font-weight:700;content:""}.checkbox-slider--default input:checked+span:after{margin-left:20px;content:""}.checkbox-slider--default input:checked+span:before{transition:background .2s ease-in}.checkbox-slider--default input+span:after{background:#FFF;border:solid transparent 1px;background-clip:content-box}.checkbox-slider--default input:checked+span:after{background:#5cb85c;border:solid transparent 1px;background-clip:content-box}.checkbox-slider--a-rounded{position:relative}.checkbox-slider--a-rounded input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-slider--a-rounded input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-slider--a-rounded input+span{cursor:pointer;user-select:none}.checkbox-slider--a-rounded input+span:before{position:absolute;left:0;display:inline-block}.checkbox-slider--a-rounded input+span>h4{display:inline}.checkbox-slider--a-rounded input+span{padding-left:40px}.checkbox-slider--a-rounded input+span:before{content:"";height:20px;width:40px;background:rgba(100,100,100,.2);box-shadow:inset 0 0 5px rgba(0,0,0,.8);transition:background .2s ease-out}.checkbox-slider--a-rounded input+span:after{width:20px;height:20px;position:absolute;left:0;top:0;display:block;background:#FFF;transition:margin-left .1s ease-in-out;text-align:center;font-weight:700;content:""}.checkbox-slider--a-rounded input:checked+span:after{margin-left:20px;content:""}.checkbox-slider--a-rounded input:checked+span:before{transition:background .2s ease-in}.checkbox-slider--a-rounded input+span:after{background:#FFF;border:solid transparent 1px;background-clip:content-box}.checkbox-slider--a-rounded input:checked+span:after{background:#5cb85c;border:solid transparent 1px;background-clip:content-box}.checkbox-slider--a-rounded input+span:after,.checkbox-slider--a-rounded input+span:before{border-radius:4px}.checkbox-slider--a-rounded input+span:after,.checkbox-slider--a-rounded input:checked+span:after{border:solid transparent 2px;background-clip:content-box}.checkbox-slider--a-rounded.checkbox-slider-sm input+span:before,.checkbox-slider--a-rounded.checkbox-slider-sm input+span:after{border-radius:3px}.checkbox-slider--a-rounded.checkbox-slider-md input+span:before,.checkbox-slider--a-rounded.checkbox-slider-md input+span:after{border-radius:4px}.checkbox-slider--a-rounded.checkbox-slider-lg input+span:before,.checkbox-slider--a-rounded.checkbox-slider-lg input+span:after{border-radius:6px}.checkbox-slider--a{position:relative}.checkbox-slider--a input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-slider--a input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-slider--a input+span{cursor:pointer;user-select:none}.checkbox-slider--a input+span:before{position:absolute;left:0;display:inline-block}.checkbox-slider--a input+span>h4{display:inline}.checkbox-slider--a input+span{padding-left:40px}.checkbox-slider--a input+span:before{content:"";height:20px;width:40px;background:rgba(100,100,100,.2);box-shadow:inset 0 0 5px rgba(0,0,0,.8);transition:background .2s ease-out}.checkbox-slider--a input+span:after{width:20px;height:20px;position:absolute;left:0;top:0;display:block;background:#FFF;transition:margin-left .1s ease-in-out;text-align:center;font-weight:700;content:""}.checkbox-slider--a input:checked+span:after{margin-left:20px;content:""}.checkbox-slider--a input:checked+span:before{transition:background .2s ease-in}.checkbox-slider--a input+span{padding-left:60px}.checkbox-slider--a input+span:before{content:"";width:60px}.checkbox-slider--a input+span:after{width:40px;font-size:10px;color:#000;content:"Off";border:solid transparent 1px;background-clip:content-box}.checkbox-slider--a input:checked+span:after{content:"On";color:#fff;background:#5cb85c;border:solid transparent 1px;background-clip:content-box}.checkbox-slider--a.checkbox-slider-sm input+span{padding-left:30px}.checkbox-slider--a.checkbox-slider-sm input+span:before{width:30px}.checkbox-slider--a.checkbox-slider-sm input+span:after{width:20px;font-size:5px}.checkbox-slider--a.checkbox-slider-sm input:checked+span:after{margin-left:10px}.checkbox-slider--a.checkbox-slider-md input+span{padding-left:90px}.checkbox-slider--a.checkbox-slider-md input+span:before{width:90px}.checkbox-slider--a.checkbox-slider-md input+span:after{width:60px;font-size:15px}.checkbox-slider--a.checkbox-slider-md input:checked+span:after{margin-left:30px}.checkbox-slider--a.checkbox-slider-lg input+span{padding-left:120px}.checkbox-slider--a.checkbox-slider-lg input+span:before{width:120px}.checkbox-slider--a.checkbox-slider-lg input+span:after{width:80px;font-size:20px}.checkbox-slider--a.checkbox-slider-lg input:checked+span:after{margin-left:40px}.checkbox-slider--b{position:relative}.checkbox-slider--b input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-slider--b input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-slider--b input+span{cursor:pointer;user-select:none}.checkbox-slider--b input+span:before{position:absolute;left:0;display:inline-block}.checkbox-slider--b input+span>h4{display:inline}.checkbox-slider--b input+span{padding-left:40px}.checkbox-slider--b input+span:before{content:"";height:20px;width:40px;background:rgba(100,100,100,.2);box-shadow:inset 0 0 5px rgba(0,0,0,.8);transition:background .2s ease-out}.checkbox-slider--b input+span:after{width:20px;height:20px;position:absolute;left:0;top:0;display:block;background:#FFF;transition:margin-left .1s ease-in-out;text-align:center;font-weight:700;content:""}.checkbox-slider--b input:checked+span:after{margin-left:20px;content:""}.checkbox-slider--b input:checked+span:before{transition:background .2s ease-in}.checkbox-slider--b input+span{padding-left:40px}.checkbox-slider--b input+span:before{border-radius:20px;width:40px}.checkbox-slider--b input+span:after{background:#FFF;content:"";width:20px;border:solid transparent 2px;background-clip:padding-box;border-radius:20px}.checkbox-slider--b input:not(:checked)+span:after{animation:popOut ease-in .3s normal}.checkbox-slider--b input:checked+span:after{content:"";margin-left:20px;border:solid transparent 2px;background-clip:padding-box;animation:popIn ease-in .3s normal}.checkbox-slider--b input:checked+span:before{background:#5cb85c}.checkbox-slider--b.checkbox-slider-md input+span:before{border-radius:30px}.checkbox-slider--b.checkbox-slider-md input+span:after{border-radius:30px}.checkbox-slider--b.checkbox-slider-lg input+span:before{border-radius:40px}.checkbox-slider--b.checkbox-slider-lg input+span:after{border-radius:40px}.checkbox-slider--b-flat{position:relative}.checkbox-slider--b-flat input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-slider--b-flat input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-slider--b-flat input+span{cursor:pointer;user-select:none}.checkbox-slider--b-flat input+span:before{position:absolute;left:0;display:inline-block}.checkbox-slider--b-flat input+span>h4{display:inline}.checkbox-slider--b-flat input+span{padding-left:40px}.checkbox-slider--b-flat input+span:before{content:"";height:20px;width:40px;background:rgba(100,100,100,.2);box-shadow:inset 0 0 5px rgba(0,0,0,.8);transition:background .2s ease-out}.checkbox-slider--b-flat input+span:after{width:20px;height:20px;position:absolute;left:0;top:0;display:block;background:#FFF;transition:margin-left .1s ease-in-out;text-align:center;font-weight:700;content:""}.checkbox-slider--b-flat input:checked+span:after{margin-left:20px;content:""}.checkbox-slider--b-flat input:checked+span:before{transition:background .2s ease-in}.checkbox-slider--b-flat input+span{padding-left:40px}.checkbox-slider--b-flat input+span:before{border-radius:20px;width:40px}.checkbox-slider--b-flat input+span:after{background:#FFF;content:"";width:20px;border:solid transparent 2px;background-clip:padding-box;border-radius:20px}.checkbox-slider--b-flat input:not(:checked)+span:after{animation:popOut ease-in .3s normal}.checkbox-slider--b-flat input:checked+span:after{content:"";margin-left:20px;border:solid transparent 2px;background-clip:padding-box;animation:popIn ease-in .3s normal}.checkbox-slider--b-flat input:checked+span:before{background:#5cb85c}.checkbox-slider--b-flat.checkbox-slider-md input+span:before{border-radius:30px}.checkbox-slider--b-flat.checkbox-slider-md input+span:after{border-radius:30px}.checkbox-slider--b-flat.checkbox-slider-lg input+span:before{border-radius:40px}.checkbox-slider--b-flat.checkbox-slider-lg input+span:after{border-radius:40px}.checkbox-slider--b-flat input+span:before{box-shadow:none}.checkbox-slider--c{position:relative}.checkbox-slider--c input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-slider--c input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-slider--c input+span{cursor:pointer;user-select:none}.checkbox-slider--c input+span:before{position:absolute;left:0;display:inline-block}.checkbox-slider--c input+span>h4{display:inline}.checkbox-slider--c input+span{padding-left:40px}.checkbox-slider--c input+span:before{content:"";height:20px;width:40px;background:rgba(100,100,100,.2);box-shadow:inset 0 0 5px rgba(0,0,0,.8);transition:background .2s ease-out}.checkbox-slider--c input+span:after{width:20px;height:20px;position:absolute;left:0;top:0;display:block;background:#FFF;transition:margin-left .1s ease-in-out;text-align:center;font-weight:700;content:""}.checkbox-slider--c input:checked+span:after{margin-left:20px;content:""}.checkbox-slider--c input:checked+span:before{transition:background .2s ease-in}.checkbox-slider--c input+span{padding-left:40px}.checkbox-slider--c input+span:before{height:2px!important;top:10px;box-shadow:none;width:40px;background:#555}.checkbox-slider--c input+span:after{box-shadow:none;width:20px;border:solid #555 2px;border-radius:20px}.checkbox-slider--c input:checked+span:after{background:#5cb85c;margin-left:20px;border:solid #5cb85c 2px;animation:splashIn ease-in .3s normal}.checkbox-slider--c input:checked+span:before{background:#5cb85c}.checkbox-slider--c.checkbox-slider-sm input+span:before{top:4px}.checkbox-slider--c.checkbox-slider-md input+span:before{top:14px}.checkbox-slider--c.checkbox-slider-md input+span:after{width:30px;border-radius:30px}.checkbox-slider--c.checkbox-slider-lg input+span:before{top:19px}.checkbox-slider--c.checkbox-slider-lg input+span:after{width:40px;border-radius:40px}.form-horizontal [class*=checkbox-slider--c].checkbox-slider-sm input+span:before{top:10px}.form-horizontal [class*=checkbox-slider--c].checkbox-slider-md input+span:before{top:20px}.form-horizontal [class*=checkbox-slider--c].checkbox-slider-lg input+span:before{top:25px}.checkbox-slider--c-weight{position:relative}.checkbox-slider--c-weight input[type=checkbox]{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:0;height:0;margin:0;cursor:pointer;opacity:0}.checkbox-slider--c-weight input[type=checkbox]:focus+*:before{outline:solid #66afe9 2px}.checkbox-slider--c-weight input+span{cursor:pointer;user-select:none}.checkbox-slider--c-weight input+span:before{position:absolute;left:0;display:inline-block}.checkbox-slider--c-weight input+span>h4{display:inline}.checkbox-slider--c-weight input+span{padding-left:40px}.checkbox-slider--c-weight input+span:before{content:"";height:20px;width:40px;background:rgba(100,100,100,.2);box-shadow:inset 0 0 5px rgba(0,0,0,.8);transition:background .2s ease-out}.checkbox-slider--c-weight input+span:after{width:20px;height:20px;position:absolute;left:0;top:0;display:block;background:#FFF;transition:margin-left .1s ease-in-out;text-align:center;font-weight:700;content:""}.checkbox-slider--c-weight input:checked+span:after{margin-left:20px;content:""}.checkbox-slider--c-weight input:checked+span:before{transition:background .2s ease-in}.checkbox-slider--c-weight input+span{padding-left:40px}.checkbox-slider--c-weight input+span:before{height:2px!important;top:10px;box-shadow:none;width:40px;background:#555}.checkbox-slider--c-weight input+span:after{box-shadow:none;width:20px;border:solid #555 2px;border-radius:20px}.checkbox-slider--c-weight input:checked+span:after{background:#5cb85c;margin-left:20px;border:solid #5cb85c 2px;animation:splashIn ease-in .3s normal}.checkbox-slider--c-weight input:checked+span:before{background:#5cb85c}.checkbox-slider--c-weight.checkbox-slider-sm input+span:before{top:4px}.checkbox-slider--c-weight.checkbox-slider-md input+span:before{top:14px}.checkbox-slider--c-weight.checkbox-slider-md input+span:after{width:30px;border-radius:30px}.checkbox-slider--c-weight.checkbox-slider-lg input+span:before{top:19px}.checkbox-slider--c-weight.checkbox-slider-lg input+span:after{width:40px;border-radius:40px}.checkbox-slider--c-weight input+span:before{height:1px!important}.checkbox-slider--c-weight input:checked+span:before{height:2px!important}.checkbox-slider--c-weight input:not(:checked)+span:after{transform:scale(.7);left:-6px}.checkbox-slider--default input:disabled+span:after{background:#777}.checkbox-slider--default input:disabled+span:before{box-shadow:0 0 0 black}.checkbox-slider--default input:disabled+span{color:#777}.checkbox-slider--a input:disabled+span:after{background:#777;color:#FFF}.checkbox-slider--a input:disabled+span:before{box-shadow:0 0 0 black}.checkbox-slider--a input:disabled+span{color:#777}.checkbox-slider--b input:disabled+span:after{border:solid transparent 2px;border-radius:40px}.checkbox-slider--b input:disabled+span:before{box-shadow:0 0 0 black}.checkbox-slider--b input:disabled+span{color:#777}.checkbox-slider--c input:disabled:checked+span:after{background:#777}.checkbox-slider--c input:disabled+span:after{border-color:#777}.checkbox-slider--c input:disabled+span:before{background:#777}.checkbox-slider--c input:disabled+span{color:#777}input:checked+.indicator-success{color:#5cb85c}input:checked+.indicator-info{color:#5bc0de}input:checked+.indicator-warning{color:#f0ad4e}input:checked+.indicator-danger{color:#d9534f}.checkbox-slider-sm{line-height:10px}.checkbox-slider-sm input+span{padding-left:20px}.checkbox-slider-sm input+span:before{width:20px}.checkbox-slider-sm input+span:after,.checkbox-slider-sm input+span:before{height:10px;line-height:10px}.checkbox-slider-sm input+span:after{width:10px;vertical-align:middle}.checkbox-slider-sm input:checked+span:after{margin-left:10px}.checkbox-slider-md{line-height:30px}.checkbox-slider-md input+span{padding-left:60px}.checkbox-slider-md input+span:before{width:60px}.checkbox-slider-md input+span:after,.checkbox-slider-md input+span:before{height:30px;line-height:30px}.checkbox-slider-md input+span:after{width:30px;vertical-align:middle}.checkbox-slider-md input:checked+span:after{margin-left:30px}.checkbox-slider-lg{line-height:40px}.checkbox-slider-lg input+span{padding-left:80px}.checkbox-slider-lg input+span:before{width:80px}.checkbox-slider-lg input+span:after,.checkbox-slider-lg input+span:before{height:40px;line-height:40px}.checkbox-slider-lg input+span:after{width:40px;vertical-align:middle}.checkbox-slider-lg input:checked+span:after{margin-left:40px}.checkbox-slider-info.checkbox-slider--default input:checked+span:after,.checkbox-slider-info.checkbox-slider--a input:checked+span:after,.checkbox-slider-info.checkbox-slider--a-rounded input:checked+span:after,.checkbox-slider-info.checkbox-slider--c input:checked+span:after,.checkbox-slider-info.checkbox-slider--c-weight input:checked+span:after{background:#5bc0de;background-clip:content-box}.checkbox-slider-info.checkbox-slider--c input:checked+span:after,.checkbox-slider-info.checkbox-slider--c-weight input:checked+span:after{border-color:#5bc0de}.checkbox-slider-info.checkbox-slider--b input:checked+span:before,.checkbox-slider-info.checkbox-slider--b-flat input:checked+span:before,.checkbox-slider-info.checkbox-slider--c input:checked+span:before,.checkbox-slider-info.checkbox-slider--c-weight input:checked+span:before{background:#5bc0de}.checkbox-slider-warning.checkbox-slider--default input:checked+span:after,.checkbox-slider-warning.checkbox-slider--a input:checked+span:after,.checkbox-slider-warning.checkbox-slider--a-rounded input:checked+span:after,.checkbox-slider-warning.checkbox-slider--c input:checked+span:after,.checkbox-slider-warning.checkbox-slider--c-weight input:checked+span:after{background:#f0ad4e;background-clip:content-box}.checkbox-slider-warning.checkbox-slider--c input:checked+span:after,.checkbox-slider-warning.checkbox-slider--c-weight input:checked+span:after{border-color:#f0ad4e}.checkbox-slider-warning.checkbox-slider--b input:checked+span:before,.checkbox-slider-warning.checkbox-slider--b-flat input:checked+span:before,.checkbox-slider-warning.checkbox-slider--c input:checked+span:before,.checkbox-slider-warning.checkbox-slider--c-weight input:checked+span:before{background:#f0ad4e}.checkbox-slider-danger.checkbox-slider--default input:checked+span:after,.checkbox-slider-danger.checkbox-slider--a input:checked+span:after,.checkbox-slider-danger.checkbox-slider--a-rounded input:checked+span:after,.checkbox-slider-danger.checkbox-slider--c input:checked+span:after,.checkbox-slider-danger.checkbox-slider--c-weight input:checked+span:after{background:#d9534f;background-clip:content-box}.checkbox-slider-danger.checkbox-slider--c input:checked+span:after,.checkbox-slider-danger.checkbox-slider--c-weight input:checked+span:after{border-color:#d9534f}.checkbox-slider-danger.checkbox-slider--b input:checked+span:before,.checkbox-slider-danger.checkbox-slider--b-flat input:checked+span:before,.checkbox-slider-danger.checkbox-slider--c input:checked+span:before,.checkbox-slider-danger.checkbox-slider--c-weight input:checked+span:before{background:#d9534f}.btn-social{position:relative;padding-left:46px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-social>:first-child{position:absolute;left:0;top:0;bottom:0;width:34px;line-height:36px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,.2)}.btn-social.btn-lg{padding-left:64px}.btn-social.btn-lg :first-child{line-height:48px;width:48px;font-size:1.8em}.btn-social.btn-sm{padding-left:41px}.btn-social.btn-sm :first-child{line-height:31px;width:31px;font-size:1.4em}.btn-social.btn-xs{padding-left:32px}.btn-social.btn-xs :first-child{line-height:22px;width:22px;font-size:1.2em}.btn-social-icon{position:relative;padding-left:46px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:36px;width:36px;padding:0}.btn-social-icon>:first-child{position:absolute;left:0;top:0;bottom:0;width:34px;line-height:36px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,.2)}.btn-social-icon.btn-lg{padding-left:64px}.btn-social-icon.btn-lg :first-child{line-height:48px;width:48px;font-size:1.8em}.btn-social-icon.btn-sm{padding-left:41px}.btn-social-icon.btn-sm :first-child{line-height:31px;width:31px;font-size:1.4em}.btn-social-icon.btn-xs{padding-left:32px}.btn-social-icon.btn-xs :first-child{line-height:22px;width:22px;font-size:1.2em}.btn-social-icon :first-child{border:none;text-align:center;width:100%!important}.btn-social-icon.btn-lg{height:48px;width:48px;padding-left:0;padding-right:0}.btn-social-icon.btn-sm{height:33px;width:33px;padding-left:0;padding-right:0}.btn-social-icon.btn-xs{height:24px;width:24px;padding-left:0;padding-right:0}.btn-adn{color:#fff;background-color:#d87a68;border-color:rgba(0,0,0,.2)}.btn-adn:hover,.btn-adn:focus,.btn-adn.focus,.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,.2)}.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{background-image:none}.btn-adn.disabled,.btn-adn[disabled],fieldset[disabled] .btn-adn,.btn-adn.disabled:hover,.btn-adn[disabled]:hover,fieldset[disabled] .btn-adn:hover,.btn-adn.disabled:focus,.btn-adn[disabled]:focus,fieldset[disabled] .btn-adn:focus,.btn-adn.disabled.focus,.btn-adn[disabled].focus,fieldset[disabled] .btn-adn.focus,.btn-adn.disabled:active,.btn-adn[disabled]:active,fieldset[disabled] .btn-adn:active,.btn-adn.disabled.active,.btn-adn[disabled].active,fieldset[disabled] .btn-adn.active{background-color:#d87a68;border-color:rgba(0,0,0,.2)}.btn-adn .badge{color:#d87a68;background-color:#fff}.btn-bitbucket{color:#fff;background-color:#205081;border-color:rgba(0,0,0,.2)}.btn-bitbucket:hover,.btn-bitbucket:focus,.btn-bitbucket.focus,.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{color:#fff;background-color:#163758;border-color:rgba(0,0,0,.2)}.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{background-image:none}.btn-bitbucket.disabled,.btn-bitbucket[disabled],fieldset[disabled] .btn-bitbucket,.btn-bitbucket.disabled:hover,.btn-bitbucket[disabled]:hover,fieldset[disabled] .btn-bitbucket:hover,.btn-bitbucket.disabled:focus,.btn-bitbucket[disabled]:focus,fieldset[disabled] .btn-bitbucket:focus,.btn-bitbucket.disabled.focus,.btn-bitbucket[disabled].focus,fieldset[disabled] .btn-bitbucket.focus,.btn-bitbucket.disabled:active,.btn-bitbucket[disabled]:active,fieldset[disabled] .btn-bitbucket:active,.btn-bitbucket.disabled.active,.btn-bitbucket[disabled].active,fieldset[disabled] .btn-bitbucket.active{background-color:#205081;border-color:rgba(0,0,0,.2)}.btn-bitbucket .badge{color:#205081;background-color:#fff}.btn-dropbox{color:#fff;background-color:#1087dd;border-color:rgba(0,0,0,.2)}.btn-dropbox:hover,.btn-dropbox:focus,.btn-dropbox.focus,.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,.2)}.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{background-image:none}.btn-dropbox.disabled,.btn-dropbox[disabled],fieldset[disabled] .btn-dropbox,.btn-dropbox.disabled:hover,.btn-dropbox[disabled]:hover,fieldset[disabled] .btn-dropbox:hover,.btn-dropbox.disabled:focus,.btn-dropbox[disabled]:focus,fieldset[disabled] .btn-dropbox:focus,.btn-dropbox.disabled.focus,.btn-dropbox[disabled].focus,fieldset[disabled] .btn-dropbox.focus,.btn-dropbox.disabled:active,.btn-dropbox[disabled]:active,fieldset[disabled] .btn-dropbox:active,.btn-dropbox.disabled.active,.btn-dropbox[disabled].active,fieldset[disabled] .btn-dropbox.active{background-color:#1087dd;border-color:rgba(0,0,0,.2)}.btn-dropbox .badge{color:#1087dd;background-color:#fff}.btn-facebook{color:#fff;background-color:#3b5998;border-color:rgba(0,0,0,.2)}.btn-facebook:hover,.btn-facebook:focus,.btn-facebook.focus,.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,.2)}.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{background-image:none}.btn-facebook.disabled,.btn-facebook[disabled],fieldset[disabled] .btn-facebook,.btn-facebook.disabled:hover,.btn-facebook[disabled]:hover,fieldset[disabled] .btn-facebook:hover,.btn-facebook.disabled:focus,.btn-facebook[disabled]:focus,fieldset[disabled] .btn-facebook:focus,.btn-facebook.disabled.focus,.btn-facebook[disabled].focus,fieldset[disabled] .btn-facebook.focus,.btn-facebook.disabled:active,.btn-facebook[disabled]:active,fieldset[disabled] .btn-facebook:active,.btn-facebook.disabled.active,.btn-facebook[disabled].active,fieldset[disabled] .btn-facebook.active{background-color:#3b5998;border-color:rgba(0,0,0,.2)}.btn-facebook .badge{color:#3b5998;background-color:#fff}.btn-flickr{color:#fff;background-color:#ff0084;border-color:rgba(0,0,0,.2)}.btn-flickr:hover,.btn-flickr:focus,.btn-flickr.focus,.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,.2)}.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{background-image:none}.btn-flickr.disabled,.btn-flickr[disabled],fieldset[disabled] .btn-flickr,.btn-flickr.disabled:hover,.btn-flickr[disabled]:hover,fieldset[disabled] .btn-flickr:hover,.btn-flickr.disabled:focus,.btn-flickr[disabled]:focus,fieldset[disabled] .btn-flickr:focus,.btn-flickr.disabled.focus,.btn-flickr[disabled].focus,fieldset[disabled] .btn-flickr.focus,.btn-flickr.disabled:active,.btn-flickr[disabled]:active,fieldset[disabled] .btn-flickr:active,.btn-flickr.disabled.active,.btn-flickr[disabled].active,fieldset[disabled] .btn-flickr.active{background-color:#ff0084;border-color:rgba(0,0,0,.2)}.btn-flickr .badge{color:#ff0084;background-color:#fff}.btn-foursquare{color:#fff;background-color:#f94877;border-color:rgba(0,0,0,.2)}.btn-foursquare:hover,.btn-foursquare:focus,.btn-foursquare.focus,.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,.2)}.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{background-image:none}.btn-foursquare.disabled,.btn-foursquare[disabled],fieldset[disabled] .btn-foursquare,.btn-foursquare.disabled:hover,.btn-foursquare[disabled]:hover,fieldset[disabled] .btn-foursquare:hover,.btn-foursquare.disabled:focus,.btn-foursquare[disabled]:focus,fieldset[disabled] .btn-foursquare:focus,.btn-foursquare.disabled.focus,.btn-foursquare[disabled].focus,fieldset[disabled] .btn-foursquare.focus,.btn-foursquare.disabled:active,.btn-foursquare[disabled]:active,fieldset[disabled] .btn-foursquare:active,.btn-foursquare.disabled.active,.btn-foursquare[disabled].active,fieldset[disabled] .btn-foursquare.active{background-color:#f94877;border-color:rgba(0,0,0,.2)}.btn-foursquare .badge{color:#f94877;background-color:#fff}.btn-github{color:#fff;background-color:#444;border-color:rgba(0,0,0,.2)}.btn-github:hover,.btn-github:focus,.btn-github.focus,.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,.2)}.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{background-image:none}.btn-github.disabled,.btn-github[disabled],fieldset[disabled] .btn-github,.btn-github.disabled:hover,.btn-github[disabled]:hover,fieldset[disabled] .btn-github:hover,.btn-github.disabled:focus,.btn-github[disabled]:focus,fieldset[disabled] .btn-github:focus,.btn-github.disabled.focus,.btn-github[disabled].focus,fieldset[disabled] .btn-github.focus,.btn-github.disabled:active,.btn-github[disabled]:active,fieldset[disabled] .btn-github:active,.btn-github.disabled.active,.btn-github[disabled].active,fieldset[disabled] .btn-github.active{background-color:#444;border-color:rgba(0,0,0,.2)}.btn-github .badge{color:#444;background-color:#fff}.btn-google-plus{color:#fff;background-color:#dd4b39;border-color:rgba(0,0,0,.2)}.btn-google-plus:hover,.btn-google-plus:focus,.btn-google-plus.focus,.btn-google-plus:active,.btn-google-plus.active,.open>.dropdown-toggle.btn-google-plus{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,.2)}.btn-google-plus:active,.btn-google-plus.active,.open>.dropdown-toggle.btn-google-plus{background-image:none}.btn-google-plus.disabled,.btn-google-plus[disabled],fieldset[disabled] .btn-google-plus,.btn-google-plus.disabled:hover,.btn-google-plus[disabled]:hover,fieldset[disabled] .btn-google-plus:hover,.btn-google-plus.disabled:focus,.btn-google-plus[disabled]:focus,fieldset[disabled] .btn-google-plus:focus,.btn-google-plus.disabled.focus,.btn-google-plus[disabled].focus,fieldset[disabled] .btn-google-plus.focus,.btn-google-plus.disabled:active,.btn-google-plus[disabled]:active,fieldset[disabled] .btn-google-plus:active,.btn-google-plus.disabled.active,.btn-google-plus[disabled].active,fieldset[disabled] .btn-google-plus.active{background-color:#dd4b39;border-color:rgba(0,0,0,.2)}.btn-google-plus .badge{color:#dd4b39;background-color:#fff}.btn-instagram{color:#fff;background-color:#3f729b;border-color:rgba(0,0,0,.2)}.btn-instagram:hover,.btn-instagram:focus,.btn-instagram.focus,.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{color:#fff;background-color:#305777;border-color:rgba(0,0,0,.2)}.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{background-image:none}.btn-instagram.disabled,.btn-instagram[disabled],fieldset[disabled] .btn-instagram,.btn-instagram.disabled:hover,.btn-instagram[disabled]:hover,fieldset[disabled] .btn-instagram:hover,.btn-instagram.disabled:focus,.btn-instagram[disabled]:focus,fieldset[disabled] .btn-instagram:focus,.btn-instagram.disabled.focus,.btn-instagram[disabled].focus,fieldset[disabled] .btn-instagram.focus,.btn-instagram.disabled:active,.btn-instagram[disabled]:active,fieldset[disabled] .btn-instagram:active,.btn-instagram.disabled.active,.btn-instagram[disabled].active,fieldset[disabled] .btn-instagram.active{background-color:#3f729b;border-color:rgba(0,0,0,.2)}.btn-instagram .badge{color:#3f729b;background-color:#fff}.btn-linkedin{color:#fff;background-color:#007bb6;border-color:rgba(0,0,0,.2)}.btn-linkedin:hover,.btn-linkedin:focus,.btn-linkedin.focus,.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{color:#fff;background-color:#005983;border-color:rgba(0,0,0,.2)}.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{background-image:none}.btn-linkedin.disabled,.btn-linkedin[disabled],fieldset[disabled] .btn-linkedin,.btn-linkedin.disabled:hover,.btn-linkedin[disabled]:hover,fieldset[disabled] .btn-linkedin:hover,.btn-linkedin.disabled:focus,.btn-linkedin[disabled]:focus,fieldset[disabled] .btn-linkedin:focus,.btn-linkedin.disabled.focus,.btn-linkedin[disabled].focus,fieldset[disabled] .btn-linkedin.focus,.btn-linkedin.disabled:active,.btn-linkedin[disabled]:active,fieldset[disabled] .btn-linkedin:active,.btn-linkedin.disabled.active,.btn-linkedin[disabled].active,fieldset[disabled] .btn-linkedin.active{background-color:#007bb6;border-color:rgba(0,0,0,.2)}.btn-linkedin .badge{color:#007bb6;background-color:#fff}.btn-microsoft{color:#fff;background-color:#2672ec;border-color:rgba(0,0,0,.2)}.btn-microsoft:hover,.btn-microsoft:focus,.btn-microsoft.focus,.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,.2)}.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{background-image:none}.btn-microsoft.disabled,.btn-microsoft[disabled],fieldset[disabled] .btn-microsoft,.btn-microsoft.disabled:hover,.btn-microsoft[disabled]:hover,fieldset[disabled] .btn-microsoft:hover,.btn-microsoft.disabled:focus,.btn-microsoft[disabled]:focus,fieldset[disabled] .btn-microsoft:focus,.btn-microsoft.disabled.focus,.btn-microsoft[disabled].focus,fieldset[disabled] .btn-microsoft.focus,.btn-microsoft.disabled:active,.btn-microsoft[disabled]:active,fieldset[disabled] .btn-microsoft:active,.btn-microsoft.disabled.active,.btn-microsoft[disabled].active,fieldset[disabled] .btn-microsoft.active{background-color:#2672ec;border-color:rgba(0,0,0,.2)}.btn-microsoft .badge{color:#2672ec;background-color:#fff}.btn-openid{color:#fff;background-color:#f7931e;border-color:rgba(0,0,0,.2)}.btn-openid:hover,.btn-openid:focus,.btn-openid.focus,.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,.2)}.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{background-image:none}.btn-openid.disabled,.btn-openid[disabled],fieldset[disabled] .btn-openid,.btn-openid.disabled:hover,.btn-openid[disabled]:hover,fieldset[disabled] .btn-openid:hover,.btn-openid.disabled:focus,.btn-openid[disabled]:focus,fieldset[disabled] .btn-openid:focus,.btn-openid.disabled.focus,.btn-openid[disabled].focus,fieldset[disabled] .btn-openid.focus,.btn-openid.disabled:active,.btn-openid[disabled]:active,fieldset[disabled] .btn-openid:active,.btn-openid.disabled.active,.btn-openid[disabled].active,fieldset[disabled] .btn-openid.active{background-color:#f7931e;border-color:rgba(0,0,0,.2)}.btn-openid .badge{color:#f7931e;background-color:#fff}.btn-pinterest{color:#fff;background-color:#cb2027;border-color:rgba(0,0,0,.2)}.btn-pinterest:hover,.btn-pinterest:focus,.btn-pinterest.focus,.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,.2)}.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{background-image:none}.btn-pinterest.disabled,.btn-pinterest[disabled],fieldset[disabled] .btn-pinterest,.btn-pinterest.disabled:hover,.btn-pinterest[disabled]:hover,fieldset[disabled] .btn-pinterest:hover,.btn-pinterest.disabled:focus,.btn-pinterest[disabled]:focus,fieldset[disabled] .btn-pinterest:focus,.btn-pinterest.disabled.focus,.btn-pinterest[disabled].focus,fieldset[disabled] .btn-pinterest.focus,.btn-pinterest.disabled:active,.btn-pinterest[disabled]:active,fieldset[disabled] .btn-pinterest:active,.btn-pinterest.disabled.active,.btn-pinterest[disabled].active,fieldset[disabled] .btn-pinterest.active{background-color:#cb2027;border-color:rgba(0,0,0,.2)}.btn-pinterest .badge{color:#cb2027;background-color:#fff}.btn-reddit{color:#000;background-color:#eff7ff;border-color:rgba(0,0,0,.2)}.btn-reddit:hover,.btn-reddit:focus,.btn-reddit.focus,.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,.2)}.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{background-image:none}.btn-reddit.disabled,.btn-reddit[disabled],fieldset[disabled] .btn-reddit,.btn-reddit.disabled:hover,.btn-reddit[disabled]:hover,fieldset[disabled] .btn-reddit:hover,.btn-reddit.disabled:focus,.btn-reddit[disabled]:focus,fieldset[disabled] .btn-reddit:focus,.btn-reddit.disabled.focus,.btn-reddit[disabled].focus,fieldset[disabled] .btn-reddit.focus,.btn-reddit.disabled:active,.btn-reddit[disabled]:active,fieldset[disabled] .btn-reddit:active,.btn-reddit.disabled.active,.btn-reddit[disabled].active,fieldset[disabled] .btn-reddit.active{background-color:#eff7ff;border-color:rgba(0,0,0,.2)}.btn-reddit .badge{color:#eff7ff;background-color:#000}.btn-soundcloud{color:#fff;background-color:#f50;border-color:rgba(0,0,0,.2)}.btn-soundcloud:hover,.btn-soundcloud:focus,.btn-soundcloud.focus,.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{color:#fff;background-color:#c40;border-color:rgba(0,0,0,.2)}.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{background-image:none}.btn-soundcloud.disabled,.btn-soundcloud[disabled],fieldset[disabled] .btn-soundcloud,.btn-soundcloud.disabled:hover,.btn-soundcloud[disabled]:hover,fieldset[disabled] .btn-soundcloud:hover,.btn-soundcloud.disabled:focus,.btn-soundcloud[disabled]:focus,fieldset[disabled] .btn-soundcloud:focus,.btn-soundcloud.disabled.focus,.btn-soundcloud[disabled].focus,fieldset[disabled] .btn-soundcloud.focus,.btn-soundcloud.disabled:active,.btn-soundcloud[disabled]:active,fieldset[disabled] .btn-soundcloud:active,.btn-soundcloud.disabled.active,.btn-soundcloud[disabled].active,fieldset[disabled] .btn-soundcloud.active{background-color:#f50;border-color:rgba(0,0,0,.2)}.btn-soundcloud .badge{color:#f50;background-color:#fff}.btn-tumblr{color:#fff;background-color:#2c4762;border-color:rgba(0,0,0,.2)}.btn-tumblr:hover,.btn-tumblr:focus,.btn-tumblr.focus,.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,.2)}.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{background-image:none}.btn-tumblr.disabled,.btn-tumblr[disabled],fieldset[disabled] .btn-tumblr,.btn-tumblr.disabled:hover,.btn-tumblr[disabled]:hover,fieldset[disabled] .btn-tumblr:hover,.btn-tumblr.disabled:focus,.btn-tumblr[disabled]:focus,fieldset[disabled] .btn-tumblr:focus,.btn-tumblr.disabled.focus,.btn-tumblr[disabled].focus,fieldset[disabled] .btn-tumblr.focus,.btn-tumblr.disabled:active,.btn-tumblr[disabled]:active,fieldset[disabled] .btn-tumblr:active,.btn-tumblr.disabled.active,.btn-tumblr[disabled].active,fieldset[disabled] .btn-tumblr.active{background-color:#2c4762;border-color:rgba(0,0,0,.2)}.btn-tumblr .badge{color:#2c4762;background-color:#fff}.btn-twitter{color:#fff;background-color:#55acee;border-color:rgba(0,0,0,.2)}.btn-twitter:hover,.btn-twitter:focus,.btn-twitter.focus,.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,.2)}.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{background-image:none}.btn-twitter.disabled,.btn-twitter[disabled],fieldset[disabled] .btn-twitter,.btn-twitter.disabled:hover,.btn-twitter[disabled]:hover,fieldset[disabled] .btn-twitter:hover,.btn-twitter.disabled:focus,.btn-twitter[disabled]:focus,fieldset[disabled] .btn-twitter:focus,.btn-twitter.disabled.focus,.btn-twitter[disabled].focus,fieldset[disabled] .btn-twitter.focus,.btn-twitter.disabled:active,.btn-twitter[disabled]:active,fieldset[disabled] .btn-twitter:active,.btn-twitter.disabled.active,.btn-twitter[disabled].active,fieldset[disabled] .btn-twitter.active{background-color:#55acee;border-color:rgba(0,0,0,.2)}.btn-twitter .badge{color:#55acee;background-color:#fff}.btn-vimeo{color:#fff;background-color:#1ab7ea;border-color:rgba(0,0,0,.2)}.btn-vimeo:hover,.btn-vimeo:focus,.btn-vimeo.focus,.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,.2)}.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{background-image:none}.btn-vimeo.disabled,.btn-vimeo[disabled],fieldset[disabled] .btn-vimeo,.btn-vimeo.disabled:hover,.btn-vimeo[disabled]:hover,fieldset[disabled] .btn-vimeo:hover,.btn-vimeo.disabled:focus,.btn-vimeo[disabled]:focus,fieldset[disabled] .btn-vimeo:focus,.btn-vimeo.disabled.focus,.btn-vimeo[disabled].focus,fieldset[disabled] .btn-vimeo.focus,.btn-vimeo.disabled:active,.btn-vimeo[disabled]:active,fieldset[disabled] .btn-vimeo:active,.btn-vimeo.disabled.active,.btn-vimeo[disabled].active,fieldset[disabled] .btn-vimeo.active{background-color:#1ab7ea;border-color:rgba(0,0,0,.2)}.btn-vimeo .badge{color:#1ab7ea;background-color:#fff}.btn-vk{color:#fff;background-color:#587ea3;border-color:rgba(0,0,0,.2)}.btn-vk:hover,.btn-vk:focus,.btn-vk.focus,.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{color:#fff;background-color:#466482;border-color:rgba(0,0,0,.2)}.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{background-image:none}.btn-vk.disabled,.btn-vk[disabled],fieldset[disabled] .btn-vk,.btn-vk.disabled:hover,.btn-vk[disabled]:hover,fieldset[disabled] .btn-vk:hover,.btn-vk.disabled:focus,.btn-vk[disabled]:focus,fieldset[disabled] .btn-vk:focus,.btn-vk.disabled.focus,.btn-vk[disabled].focus,fieldset[disabled] .btn-vk.focus,.btn-vk.disabled:active,.btn-vk[disabled]:active,fieldset[disabled] .btn-vk:active,.btn-vk.disabled.active,.btn-vk[disabled].active,fieldset[disabled] .btn-vk.active{background-color:#587ea3;border-color:rgba(0,0,0,.2)}.btn-vk .badge{color:#587ea3;background-color:#fff}.btn-yahoo{color:#fff;background-color:#720e9e;border-color:rgba(0,0,0,.2)}.btn-yahoo:hover,.btn-yahoo:focus,.btn-yahoo.focus,.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,.2)}.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{background-image:none}.btn-yahoo.disabled,.btn-yahoo[disabled],fieldset[disabled] .btn-yahoo,.btn-yahoo.disabled:hover,.btn-yahoo[disabled]:hover,fieldset[disabled] .btn-yahoo:hover,.btn-yahoo.disabled:focus,.btn-yahoo[disabled]:focus,fieldset[disabled] .btn-yahoo:focus,.btn-yahoo.disabled.focus,.btn-yahoo[disabled].focus,fieldset[disabled] .btn-yahoo.focus,.btn-yahoo.disabled:active,.btn-yahoo[disabled]:active,fieldset[disabled] .btn-yahoo:active,.btn-yahoo.disabled.active,.btn-yahoo[disabled].active,fieldset[disabled] .btn-yahoo.active{background-color:#720e9e;border-color:rgba(0,0,0,.2)}.btn-yahoo .badge{color:#720e9e;background-color:#fff}/*! - * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.eot?v=4.5.0);src:url(../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0) format('embedded-opentype'),url(../fonts/fontawesome-webfont.woff2?v=4.5.0) format('woff2'),url(../fonts/fontawesome-webfont.woff?v=4.5.0) format('woff'),url(../fonts/fontawesome-webfont.ttf?v=4.5.0) format('truetype'),url(../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular) format('svg')}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}/*! -Ionicons, v1.5.2 -Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ -https://twitter.com/benjsperry https://twitter.com/ionicframework -MIT License: https://github.com/driftyco/ionicons -*/@font-face{font-family:Ionicons;src:url(../../../fonts/ionicons.eot?v=1.5.2);src:url(../../../fonts/ionicons.eot?v=1.5.2#iefix) format("embedded-opentype"),url(../../../fonts/ionicons.ttf?v=1.5.2) format("truetype"),url(../../../fonts/ionicons.woff?v=1.5.2) format("woff"),url(../../../fonts/ionicons.svg?v=1.5.2#Ionicons) format("svg")}.ion,.ion-loading-a,.ion-loading-b,.ion-loading-c,.ion-loading-d,.ion-looping,.ion-refreshing,.ion-ios7-reloading,.ionicons,.ion-alert:before,.ion-alert-circled:before,.ion-android-add:before,.ion-android-add-contact:before,.ion-android-alarm:before,.ion-android-archive:before,.ion-android-arrow-back:before,.ion-android-arrow-down-left:before,.ion-android-arrow-down-right:before,.ion-android-arrow-forward:before,.ion-android-arrow-up-left:before,.ion-android-arrow-up-right:before,.ion-android-battery:before,.ion-android-book:before,.ion-android-calendar:before,.ion-android-call:before,.ion-android-camera:before,.ion-android-chat:before,.ion-android-checkmark:before,.ion-android-clock:before,.ion-android-close:before,.ion-android-contact:before,.ion-android-contacts:before,.ion-android-data:before,.ion-android-developer:before,.ion-android-display:before,.ion-android-download:before,.ion-android-drawer:before,.ion-android-dropdown:before,.ion-android-earth:before,.ion-android-folder:before,.ion-android-forums:before,.ion-android-friends:before,.ion-android-hand:before,.ion-android-image:before,.ion-android-inbox:before,.ion-android-information:before,.ion-android-keypad:before,.ion-android-lightbulb:before,.ion-android-locate:before,.ion-android-location:before,.ion-android-mail:before,.ion-android-microphone:before,.ion-android-mixer:before,.ion-android-more:before,.ion-android-note:before,.ion-android-playstore:before,.ion-android-printer:before,.ion-android-promotion:before,.ion-android-reminder:before,.ion-android-remove:before,.ion-android-search:before,.ion-android-send:before,.ion-android-settings:before,.ion-android-share:before,.ion-android-social:before,.ion-android-social-user:before,.ion-android-sort:before,.ion-android-stair-drawer:before,.ion-android-star:before,.ion-android-stopwatch:before,.ion-android-storage:before,.ion-android-system-back:before,.ion-android-system-home:before,.ion-android-system-windows:before,.ion-android-timer:before,.ion-android-trash:before,.ion-android-user-menu:before,.ion-android-volume:before,.ion-android-wifi:before,.ion-aperture:before,.ion-archive:before,.ion-arrow-down-a:before,.ion-arrow-down-b:before,.ion-arrow-down-c:before,.ion-arrow-expand:before,.ion-arrow-graph-down-left:before,.ion-arrow-graph-down-right:before,.ion-arrow-graph-up-left:before,.ion-arrow-graph-up-right:before,.ion-arrow-left-a:before,.ion-arrow-left-b:before,.ion-arrow-left-c:before,.ion-arrow-move:before,.ion-arrow-resize:before,.ion-arrow-return-left:before,.ion-arrow-return-right:before,.ion-arrow-right-a:before,.ion-arrow-right-b:before,.ion-arrow-right-c:before,.ion-arrow-shrink:before,.ion-arrow-swap:before,.ion-arrow-up-a:before,.ion-arrow-up-b:before,.ion-arrow-up-c:before,.ion-asterisk:before,.ion-at:before,.ion-bag:before,.ion-battery-charging:before,.ion-battery-empty:before,.ion-battery-full:before,.ion-battery-half:before,.ion-battery-low:before,.ion-beaker:before,.ion-beer:before,.ion-bluetooth:before,.ion-bonfire:before,.ion-bookmark:before,.ion-briefcase:before,.ion-bug:before,.ion-calculator:before,.ion-calendar:before,.ion-camera:before,.ion-card:before,.ion-cash:before,.ion-chatbox:before,.ion-chatbox-working:before,.ion-chatboxes:before,.ion-chatbubble:before,.ion-chatbubble-working:before,.ion-chatbubbles:before,.ion-checkmark:before,.ion-checkmark-circled:before,.ion-checkmark-round:before,.ion-chevron-down:before,.ion-chevron-left:before,.ion-chevron-right:before,.ion-chevron-up:before,.ion-clipboard:before,.ion-clock:before,.ion-close:before,.ion-close-circled:before,.ion-close-round:before,.ion-closed-captioning:before,.ion-cloud:before,.ion-code:before,.ion-code-download:before,.ion-code-working:before,.ion-coffee:before,.ion-compass:before,.ion-compose:before,.ion-connection-bars:before,.ion-contrast:before,.ion-cube:before,.ion-disc:before,.ion-document:before,.ion-document-text:before,.ion-drag:before,.ion-earth:before,.ion-edit:before,.ion-egg:before,.ion-eject:before,.ion-email:before,.ion-eye:before,.ion-eye-disabled:before,.ion-female:before,.ion-filing:before,.ion-film-marker:before,.ion-fireball:before,.ion-flag:before,.ion-flame:before,.ion-flash:before,.ion-flash-off:before,.ion-flask:before,.ion-folder:before,.ion-fork:before,.ion-fork-repo:before,.ion-forward:before,.ion-funnel:before,.ion-game-controller-a:before,.ion-game-controller-b:before,.ion-gear-a:before,.ion-gear-b:before,.ion-grid:before,.ion-hammer:before,.ion-happy:before,.ion-headphone:before,.ion-heart:before,.ion-heart-broken:before,.ion-help:before,.ion-help-buoy:before,.ion-help-circled:before,.ion-home:before,.ion-icecream:before,.ion-icon-social-google-plus:before,.ion-icon-social-google-plus-outline:before,.ion-image:before,.ion-images:before,.ion-information:before,.ion-information-circled:before,.ion-ionic:before,.ion-ios7-alarm:before,.ion-ios7-alarm-outline:before,.ion-ios7-albums:before,.ion-ios7-albums-outline:before,.ion-ios7-americanfootball:before,.ion-ios7-americanfootball-outline:before,.ion-ios7-analytics:before,.ion-ios7-analytics-outline:before,.ion-ios7-arrow-back:before,.ion-ios7-arrow-down:before,.ion-ios7-arrow-forward:before,.ion-ios7-arrow-left:before,.ion-ios7-arrow-right:before,.ion-ios7-arrow-thin-down:before,.ion-ios7-arrow-thin-left:before,.ion-ios7-arrow-thin-right:before,.ion-ios7-arrow-thin-up:before,.ion-ios7-arrow-up:before,.ion-ios7-at:before,.ion-ios7-at-outline:before,.ion-ios7-barcode:before,.ion-ios7-barcode-outline:before,.ion-ios7-baseball:before,.ion-ios7-baseball-outline:before,.ion-ios7-basketball:before,.ion-ios7-basketball-outline:before,.ion-ios7-bell:before,.ion-ios7-bell-outline:before,.ion-ios7-bolt:before,.ion-ios7-bolt-outline:before,.ion-ios7-bookmarks:before,.ion-ios7-bookmarks-outline:before,.ion-ios7-box:before,.ion-ios7-box-outline:before,.ion-ios7-briefcase:before,.ion-ios7-briefcase-outline:before,.ion-ios7-browsers:before,.ion-ios7-browsers-outline:before,.ion-ios7-calculator:before,.ion-ios7-calculator-outline:before,.ion-ios7-calendar:before,.ion-ios7-calendar-outline:before,.ion-ios7-camera:before,.ion-ios7-camera-outline:before,.ion-ios7-cart:before,.ion-ios7-cart-outline:before,.ion-ios7-chatboxes:before,.ion-ios7-chatboxes-outline:before,.ion-ios7-chatbubble:before,.ion-ios7-chatbubble-outline:before,.ion-ios7-checkmark:before,.ion-ios7-checkmark-empty:before,.ion-ios7-checkmark-outline:before,.ion-ios7-circle-filled:before,.ion-ios7-circle-outline:before,.ion-ios7-clock:before,.ion-ios7-clock-outline:before,.ion-ios7-close:before,.ion-ios7-close-empty:before,.ion-ios7-close-outline:before,.ion-ios7-cloud:before,.ion-ios7-cloud-download:before,.ion-ios7-cloud-download-outline:before,.ion-ios7-cloud-outline:before,.ion-ios7-cloud-upload:before,.ion-ios7-cloud-upload-outline:before,.ion-ios7-cloudy:before,.ion-ios7-cloudy-night:before,.ion-ios7-cloudy-night-outline:before,.ion-ios7-cloudy-outline:before,.ion-ios7-cog:before,.ion-ios7-cog-outline:before,.ion-ios7-compose:before,.ion-ios7-compose-outline:before,.ion-ios7-contact:before,.ion-ios7-contact-outline:before,.ion-ios7-copy:before,.ion-ios7-copy-outline:before,.ion-ios7-download:before,.ion-ios7-download-outline:before,.ion-ios7-drag:before,.ion-ios7-email:before,.ion-ios7-email-outline:before,.ion-ios7-expand:before,.ion-ios7-eye:before,.ion-ios7-eye-outline:before,.ion-ios7-fastforward:before,.ion-ios7-fastforward-outline:before,.ion-ios7-filing:before,.ion-ios7-filing-outline:before,.ion-ios7-film:before,.ion-ios7-film-outline:before,.ion-ios7-flag:before,.ion-ios7-flag-outline:before,.ion-ios7-folder:before,.ion-ios7-folder-outline:before,.ion-ios7-football:before,.ion-ios7-football-outline:before,.ion-ios7-gear:before,.ion-ios7-gear-outline:before,.ion-ios7-glasses:before,.ion-ios7-glasses-outline:before,.ion-ios7-heart:before,.ion-ios7-heart-outline:before,.ion-ios7-help:before,.ion-ios7-help-empty:before,.ion-ios7-help-outline:before,.ion-ios7-home:before,.ion-ios7-home-outline:before,.ion-ios7-infinite:before,.ion-ios7-infinite-outline:before,.ion-ios7-information:before,.ion-ios7-information-empty:before,.ion-ios7-information-outline:before,.ion-ios7-ionic-outline:before,.ion-ios7-keypad:before,.ion-ios7-keypad-outline:before,.ion-ios7-lightbulb:before,.ion-ios7-lightbulb-outline:before,.ion-ios7-location:before,.ion-ios7-location-outline:before,.ion-ios7-locked:before,.ion-ios7-locked-outline:before,.ion-ios7-loop:before,.ion-ios7-loop-strong:before,.ion-ios7-medkit:before,.ion-ios7-medkit-outline:before,.ion-ios7-mic:before,.ion-ios7-mic-off:before,.ion-ios7-mic-outline:before,.ion-ios7-minus:before,.ion-ios7-minus-empty:before,.ion-ios7-minus-outline:before,.ion-ios7-monitor:before,.ion-ios7-monitor-outline:before,.ion-ios7-moon:before,.ion-ios7-moon-outline:before,.ion-ios7-more:before,.ion-ios7-more-outline:before,.ion-ios7-musical-note:before,.ion-ios7-musical-notes:before,.ion-ios7-navigate:before,.ion-ios7-navigate-outline:before,.ion-ios7-paper:before,.ion-ios7-paper-outline:before,.ion-ios7-paperplane:before,.ion-ios7-paperplane-outline:before,.ion-ios7-partlysunny:before,.ion-ios7-partlysunny-outline:before,.ion-ios7-pause:before,.ion-ios7-pause-outline:before,.ion-ios7-paw:before,.ion-ios7-paw-outline:before,.ion-ios7-people:before,.ion-ios7-people-outline:before,.ion-ios7-person:before,.ion-ios7-person-outline:before,.ion-ios7-personadd:before,.ion-ios7-personadd-outline:before,.ion-ios7-photos:before,.ion-ios7-photos-outline:before,.ion-ios7-pie:before,.ion-ios7-pie-outline:before,.ion-ios7-play:before,.ion-ios7-play-outline:before,.ion-ios7-plus:before,.ion-ios7-plus-empty:before,.ion-ios7-plus-outline:before,.ion-ios7-pricetag:before,.ion-ios7-pricetag-outline:before,.ion-ios7-pricetags:before,.ion-ios7-pricetags-outline:before,.ion-ios7-printer:before,.ion-ios7-printer-outline:before,.ion-ios7-pulse:before,.ion-ios7-pulse-strong:before,.ion-ios7-rainy:before,.ion-ios7-rainy-outline:before,.ion-ios7-recording:before,.ion-ios7-recording-outline:before,.ion-ios7-redo:before,.ion-ios7-redo-outline:before,.ion-ios7-refresh:before,.ion-ios7-refresh-empty:before,.ion-ios7-refresh-outline:before,.ion-ios7-reload:before,.ion-ios7-reverse-camera:before,.ion-ios7-reverse-camera-outline:before,.ion-ios7-rewind:before,.ion-ios7-rewind-outline:before,.ion-ios7-search:before,.ion-ios7-search-strong:before,.ion-ios7-settings:before,.ion-ios7-settings-strong:before,.ion-ios7-shrink:before,.ion-ios7-skipbackward:before,.ion-ios7-skipbackward-outline:before,.ion-ios7-skipforward:before,.ion-ios7-skipforward-outline:before,.ion-ios7-snowy:before,.ion-ios7-speedometer:before,.ion-ios7-speedometer-outline:before,.ion-ios7-star:before,.ion-ios7-star-half:before,.ion-ios7-star-outline:before,.ion-ios7-stopwatch:before,.ion-ios7-stopwatch-outline:before,.ion-ios7-sunny:before,.ion-ios7-sunny-outline:before,.ion-ios7-telephone:before,.ion-ios7-telephone-outline:before,.ion-ios7-tennisball:before,.ion-ios7-tennisball-outline:before,.ion-ios7-thunderstorm:before,.ion-ios7-thunderstorm-outline:before,.ion-ios7-time:before,.ion-ios7-time-outline:before,.ion-ios7-timer:before,.ion-ios7-timer-outline:before,.ion-ios7-toggle:before,.ion-ios7-toggle-outline:before,.ion-ios7-trash:before,.ion-ios7-trash-outline:before,.ion-ios7-undo:before,.ion-ios7-undo-outline:before,.ion-ios7-unlocked:before,.ion-ios7-unlocked-outline:before,.ion-ios7-upload:before,.ion-ios7-upload-outline:before,.ion-ios7-videocam:before,.ion-ios7-videocam-outline:before,.ion-ios7-volume-high:before,.ion-ios7-volume-low:before,.ion-ios7-wineglass:before,.ion-ios7-wineglass-outline:before,.ion-ios7-world:before,.ion-ios7-world-outline:before,.ion-ipad:before,.ion-iphone:before,.ion-ipod:before,.ion-jet:before,.ion-key:before,.ion-knife:before,.ion-laptop:before,.ion-leaf:before,.ion-levels:before,.ion-lightbulb:before,.ion-link:before,.ion-load-a:before,.ion-load-b:before,.ion-load-c:before,.ion-load-d:before,.ion-location:before,.ion-locked:before,.ion-log-in:before,.ion-log-out:before,.ion-loop:before,.ion-magnet:before,.ion-male:before,.ion-man:before,.ion-map:before,.ion-medkit:before,.ion-merge:before,.ion-mic-a:before,.ion-mic-b:before,.ion-mic-c:before,.ion-minus:before,.ion-minus-circled:before,.ion-minus-round:before,.ion-model-s:before,.ion-monitor:before,.ion-more:before,.ion-mouse:before,.ion-music-note:before,.ion-navicon:before,.ion-navicon-round:before,.ion-navigate:before,.ion-network:before,.ion-no-smoking:before,.ion-nuclear:before,.ion-outlet:before,.ion-paper-airplane:before,.ion-paperclip:before,.ion-pause:before,.ion-person:before,.ion-person-add:before,.ion-person-stalker:before,.ion-pie-graph:before,.ion-pin:before,.ion-pinpoint:before,.ion-pizza:before,.ion-plane:before,.ion-planet:before,.ion-play:before,.ion-playstation:before,.ion-plus:before,.ion-plus-circled:before,.ion-plus-round:before,.ion-podium:before,.ion-pound:before,.ion-power:before,.ion-pricetag:before,.ion-pricetags:before,.ion-printer:before,.ion-pull-request:before,.ion-qr-scanner:before,.ion-quote:before,.ion-radio-waves:before,.ion-record:before,.ion-refresh:before,.ion-reply:before,.ion-reply-all:before,.ion-ribbon-a:before,.ion-ribbon-b:before,.ion-sad:before,.ion-scissors:before,.ion-search:before,.ion-settings:before,.ion-share:before,.ion-shuffle:before,.ion-skip-backward:before,.ion-skip-forward:before,.ion-social-android:before,.ion-social-android-outline:before,.ion-social-apple:before,.ion-social-apple-outline:before,.ion-social-bitcoin:before,.ion-social-bitcoin-outline:before,.ion-social-buffer:before,.ion-social-buffer-outline:before,.ion-social-designernews:before,.ion-social-designernews-outline:before,.ion-social-dribbble:before,.ion-social-dribbble-outline:before,.ion-social-dropbox:before,.ion-social-dropbox-outline:before,.ion-social-facebook:before,.ion-social-facebook-outline:before,.ion-social-foursquare:before,.ion-social-foursquare-outline:before,.ion-social-freebsd-devil:before,.ion-social-github:before,.ion-social-github-outline:before,.ion-social-google:before,.ion-social-google-outline:before,.ion-social-googleplus:before,.ion-social-googleplus-outline:before,.ion-social-hackernews:before,.ion-social-hackernews-outline:before,.ion-social-instagram:before,.ion-social-instagram-outline:before,.ion-social-linkedin:before,.ion-social-linkedin-outline:before,.ion-social-pinterest:before,.ion-social-pinterest-outline:before,.ion-social-reddit:before,.ion-social-reddit-outline:before,.ion-social-rss:before,.ion-social-rss-outline:before,.ion-social-skype:before,.ion-social-skype-outline:before,.ion-social-tumblr:before,.ion-social-tumblr-outline:before,.ion-social-tux:before,.ion-social-twitter:before,.ion-social-twitter-outline:before,.ion-social-usd:before,.ion-social-usd-outline:before,.ion-social-vimeo:before,.ion-social-vimeo-outline:before,.ion-social-windows:before,.ion-social-windows-outline:before,.ion-social-wordpress:before,.ion-social-wordpress-outline:before,.ion-social-yahoo:before,.ion-social-yahoo-outline:before,.ion-social-youtube:before,.ion-social-youtube-outline:before,.ion-speakerphone:before,.ion-speedometer:before,.ion-spoon:before,.ion-star:before,.ion-stats-bars:before,.ion-steam:before,.ion-stop:before,.ion-thermometer:before,.ion-thumbsdown:before,.ion-thumbsup:before,.ion-toggle:before,.ion-toggle-filled:before,.ion-trash-a:before,.ion-trash-b:before,.ion-trophy:before,.ion-umbrella:before,.ion-university:before,.ion-unlocked:before,.ion-upload:before,.ion-usb:before,.ion-videocamera:before,.ion-volume-high:before,.ion-volume-low:before,.ion-volume-medium:before,.ion-volume-mute:before,.ion-wand:before,.ion-waterdrop:before,.ion-wifi:before,.ion-wineglass:before,.ion-woman:before,.ion-wrench:before,.ion-xbox:before{display:inline-block;font-family:Ionicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-spin,.ion-loading-a,.ion-loading-b,.ion-loading-c,.ion-loading-d,.ion-looping,.ion-refreshing,.ion-ios7-reloading{-webkit-animation:spin 1s infinite linear;-moz-animation:spin 1s infinite linear;-o-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.ion-loading-a{-webkit-animation-timing-function:steps(8,start);-moz-animation-timing-function:steps(8,start);animation-timing-function:steps(8,start)}.ion-alert:before{content:"\f101"}.ion-alert-circled:before{content:"\f100"}.ion-android-add:before{content:"\f2c7"}.ion-android-add-contact:before{content:"\f2c6"}.ion-android-alarm:before{content:"\f2c8"}.ion-android-archive:before{content:"\f2c9"}.ion-android-arrow-back:before{content:"\f2ca"}.ion-android-arrow-down-left:before{content:"\f2cb"}.ion-android-arrow-down-right:before{content:"\f2cc"}.ion-android-arrow-forward:before{content:"\f30f"}.ion-android-arrow-up-left:before{content:"\f2cd"}.ion-android-arrow-up-right:before{content:"\f2ce"}.ion-android-battery:before{content:"\f2cf"}.ion-android-book:before{content:"\f2d0"}.ion-android-calendar:before{content:"\f2d1"}.ion-android-call:before{content:"\f2d2"}.ion-android-camera:before{content:"\f2d3"}.ion-android-chat:before{content:"\f2d4"}.ion-android-checkmark:before{content:"\f2d5"}.ion-android-clock:before{content:"\f2d6"}.ion-android-close:before{content:"\f2d7"}.ion-android-contact:before{content:"\f2d8"}.ion-android-contacts:before{content:"\f2d9"}.ion-android-data:before{content:"\f2da"}.ion-android-developer:before{content:"\f2db"}.ion-android-display:before{content:"\f2dc"}.ion-android-download:before{content:"\f2dd"}.ion-android-drawer:before{content:"\f310"}.ion-android-dropdown:before{content:"\f2de"}.ion-android-earth:before{content:"\f2df"}.ion-android-folder:before{content:"\f2e0"}.ion-android-forums:before{content:"\f2e1"}.ion-android-friends:before{content:"\f2e2"}.ion-android-hand:before{content:"\f2e3"}.ion-android-image:before{content:"\f2e4"}.ion-android-inbox:before{content:"\f2e5"}.ion-android-information:before{content:"\f2e6"}.ion-android-keypad:before{content:"\f2e7"}.ion-android-lightbulb:before{content:"\f2e8"}.ion-android-locate:before{content:"\f2e9"}.ion-android-location:before{content:"\f2ea"}.ion-android-mail:before{content:"\f2eb"}.ion-android-microphone:before{content:"\f2ec"}.ion-android-mixer:before{content:"\f2ed"}.ion-android-more:before{content:"\f2ee"}.ion-android-note:before{content:"\f2ef"}.ion-android-playstore:before{content:"\f2f0"}.ion-android-printer:before{content:"\f2f1"}.ion-android-promotion:before{content:"\f2f2"}.ion-android-reminder:before{content:"\f2f3"}.ion-android-remove:before{content:"\f2f4"}.ion-android-search:before{content:"\f2f5"}.ion-android-send:before{content:"\f2f6"}.ion-android-settings:before{content:"\f2f7"}.ion-android-share:before{content:"\f2f8"}.ion-android-social:before{content:"\f2fa"}.ion-android-social-user:before{content:"\f2f9"}.ion-android-sort:before{content:"\f2fb"}.ion-android-stair-drawer:before{content:"\f311"}.ion-android-star:before{content:"\f2fc"}.ion-android-stopwatch:before{content:"\f2fd"}.ion-android-storage:before{content:"\f2fe"}.ion-android-system-back:before{content:"\f2ff"}.ion-android-system-home:before{content:"\f300"}.ion-android-system-windows:before{content:"\f301"}.ion-android-timer:before{content:"\f302"}.ion-android-trash:before{content:"\f303"}.ion-android-user-menu:before{content:"\f312"}.ion-android-volume:before{content:"\f304"}.ion-android-wifi:before{content:"\f305"}.ion-aperture:before{content:"\f313"}.ion-archive:before{content:"\f102"}.ion-arrow-down-a:before{content:"\f103"}.ion-arrow-down-b:before{content:"\f104"}.ion-arrow-down-c:before{content:"\f105"}.ion-arrow-expand:before{content:"\f25e"}.ion-arrow-graph-down-left:before{content:"\f25f"}.ion-arrow-graph-down-right:before{content:"\f260"}.ion-arrow-graph-up-left:before{content:"\f261"}.ion-arrow-graph-up-right:before{content:"\f262"}.ion-arrow-left-a:before{content:"\f106"}.ion-arrow-left-b:before{content:"\f107"}.ion-arrow-left-c:before{content:"\f108"}.ion-arrow-move:before{content:"\f263"}.ion-arrow-resize:before{content:"\f264"}.ion-arrow-return-left:before{content:"\f265"}.ion-arrow-return-right:before{content:"\f266"}.ion-arrow-right-a:before{content:"\f109"}.ion-arrow-right-b:before{content:"\f10a"}.ion-arrow-right-c:before{content:"\f10b"}.ion-arrow-shrink:before{content:"\f267"}.ion-arrow-swap:before{content:"\f268"}.ion-arrow-up-a:before{content:"\f10c"}.ion-arrow-up-b:before{content:"\f10d"}.ion-arrow-up-c:before{content:"\f10e"}.ion-asterisk:before{content:"\f314"}.ion-at:before{content:"\f10f"}.ion-bag:before{content:"\f110"}.ion-battery-charging:before{content:"\f111"}.ion-battery-empty:before{content:"\f112"}.ion-battery-full:before{content:"\f113"}.ion-battery-half:before{content:"\f114"}.ion-battery-low:before{content:"\f115"}.ion-beaker:before{content:"\f269"}.ion-beer:before{content:"\f26a"}.ion-bluetooth:before{content:"\f116"}.ion-bonfire:before{content:"\f315"}.ion-bookmark:before{content:"\f26b"}.ion-briefcase:before{content:"\f26c"}.ion-bug:before{content:"\f2be"}.ion-calculator:before{content:"\f26d"}.ion-calendar:before{content:"\f117"}.ion-camera:before{content:"\f118"}.ion-card:before{content:"\f119"}.ion-cash:before{content:"\f316"}.ion-chatbox:before{content:"\f11b"}.ion-chatbox-working:before{content:"\f11a"}.ion-chatboxes:before{content:"\f11c"}.ion-chatbubble:before{content:"\f11e"}.ion-chatbubble-working:before{content:"\f11d"}.ion-chatbubbles:before{content:"\f11f"}.ion-checkmark:before{content:"\f122"}.ion-checkmark-circled:before{content:"\f120"}.ion-checkmark-round:before{content:"\f121"}.ion-chevron-down:before{content:"\f123"}.ion-chevron-left:before{content:"\f124"}.ion-chevron-right:before{content:"\f125"}.ion-chevron-up:before{content:"\f126"}.ion-clipboard:before{content:"\f127"}.ion-clock:before{content:"\f26e"}.ion-close:before{content:"\f12a"}.ion-close-circled:before{content:"\f128"}.ion-close-round:before{content:"\f129"}.ion-closed-captioning:before{content:"\f317"}.ion-cloud:before{content:"\f12b"}.ion-code:before{content:"\f271"}.ion-code-download:before{content:"\f26f"}.ion-code-working:before{content:"\f270"}.ion-coffee:before{content:"\f272"}.ion-compass:before{content:"\f273"}.ion-compose:before{content:"\f12c"}.ion-connection-bars:before{content:"\f274"}.ion-contrast:before{content:"\f275"}.ion-cube:before{content:"\f318"}.ion-disc:before{content:"\f12d"}.ion-document:before{content:"\f12f"}.ion-document-text:before{content:"\f12e"}.ion-drag:before{content:"\f130"}.ion-earth:before{content:"\f276"}.ion-edit:before{content:"\f2bf"}.ion-egg:before{content:"\f277"}.ion-eject:before{content:"\f131"}.ion-email:before{content:"\f132"}.ion-eye:before{content:"\f133"}.ion-eye-disabled:before{content:"\f306"}.ion-female:before{content:"\f278"}.ion-filing:before{content:"\f134"}.ion-film-marker:before{content:"\f135"}.ion-fireball:before{content:"\f319"}.ion-flag:before{content:"\f279"}.ion-flame:before{content:"\f31a"}.ion-flash:before{content:"\f137"}.ion-flash-off:before{content:"\f136"}.ion-flask:before{content:"\f138"}.ion-folder:before{content:"\f139"}.ion-fork:before{content:"\f27a"}.ion-fork-repo:before{content:"\f2c0"}.ion-forward:before{content:"\f13a"}.ion-funnel:before{content:"\f31b"}.ion-game-controller-a:before{content:"\f13b"}.ion-game-controller-b:before{content:"\f13c"}.ion-gear-a:before{content:"\f13d"}.ion-gear-b:before{content:"\f13e"}.ion-grid:before{content:"\f13f"}.ion-hammer:before{content:"\f27b"}.ion-happy:before{content:"\f31c"}.ion-headphone:before{content:"\f140"}.ion-heart:before{content:"\f141"}.ion-heart-broken:before{content:"\f31d"}.ion-help:before{content:"\f143"}.ion-help-buoy:before{content:"\f27c"}.ion-help-circled:before{content:"\f142"}.ion-home:before{content:"\f144"}.ion-icecream:before{content:"\f27d"}.ion-icon-social-google-plus:before{content:"\f146"}.ion-icon-social-google-plus-outline:before{content:"\f145"}.ion-image:before{content:"\f147"}.ion-images:before{content:"\f148"}.ion-information:before{content:"\f14a"}.ion-information-circled:before{content:"\f149"}.ion-ionic:before{content:"\f14b"}.ion-ios7-alarm:before{content:"\f14d"}.ion-ios7-alarm-outline:before{content:"\f14c"}.ion-ios7-albums:before{content:"\f14f"}.ion-ios7-albums-outline:before{content:"\f14e"}.ion-ios7-americanfootball:before{content:"\f31f"}.ion-ios7-americanfootball-outline:before{content:"\f31e"}.ion-ios7-analytics:before{content:"\f321"}.ion-ios7-analytics-outline:before{content:"\f320"}.ion-ios7-arrow-back:before{content:"\f150"}.ion-ios7-arrow-down:before{content:"\f151"}.ion-ios7-arrow-forward:before{content:"\f152"}.ion-ios7-arrow-left:before{content:"\f153"}.ion-ios7-arrow-right:before{content:"\f154"}.ion-ios7-arrow-thin-down:before{content:"\f27e"}.ion-ios7-arrow-thin-left:before{content:"\f27f"}.ion-ios7-arrow-thin-right:before{content:"\f280"}.ion-ios7-arrow-thin-up:before{content:"\f281"}.ion-ios7-arrow-up:before{content:"\f155"}.ion-ios7-at:before{content:"\f157"}.ion-ios7-at-outline:before{content:"\f156"}.ion-ios7-barcode:before{content:"\f323"}.ion-ios7-barcode-outline:before{content:"\f322"}.ion-ios7-baseball:before{content:"\f325"}.ion-ios7-baseball-outline:before{content:"\f324"}.ion-ios7-basketball:before{content:"\f327"}.ion-ios7-basketball-outline:before{content:"\f326"}.ion-ios7-bell:before{content:"\f159"}.ion-ios7-bell-outline:before{content:"\f158"}.ion-ios7-bolt:before{content:"\f15b"}.ion-ios7-bolt-outline:before{content:"\f15a"}.ion-ios7-bookmarks:before{content:"\f15d"}.ion-ios7-bookmarks-outline:before{content:"\f15c"}.ion-ios7-box:before{content:"\f15f"}.ion-ios7-box-outline:before{content:"\f15e"}.ion-ios7-briefcase:before{content:"\f283"}.ion-ios7-briefcase-outline:before{content:"\f282"}.ion-ios7-browsers:before{content:"\f161"}.ion-ios7-browsers-outline:before{content:"\f160"}.ion-ios7-calculator:before{content:"\f285"}.ion-ios7-calculator-outline:before{content:"\f284"}.ion-ios7-calendar:before{content:"\f163"}.ion-ios7-calendar-outline:before{content:"\f162"}.ion-ios7-camera:before{content:"\f165"}.ion-ios7-camera-outline:before{content:"\f164"}.ion-ios7-cart:before{content:"\f167"}.ion-ios7-cart-outline:before{content:"\f166"}.ion-ios7-chatboxes:before{content:"\f169"}.ion-ios7-chatboxes-outline:before{content:"\f168"}.ion-ios7-chatbubble:before{content:"\f16b"}.ion-ios7-chatbubble-outline:before{content:"\f16a"}.ion-ios7-checkmark:before{content:"\f16e"}.ion-ios7-checkmark-empty:before{content:"\f16c"}.ion-ios7-checkmark-outline:before{content:"\f16d"}.ion-ios7-circle-filled:before{content:"\f16f"}.ion-ios7-circle-outline:before{content:"\f170"}.ion-ios7-clock:before{content:"\f172"}.ion-ios7-clock-outline:before{content:"\f171"}.ion-ios7-close:before{content:"\f2bc"}.ion-ios7-close-empty:before{content:"\f2bd"}.ion-ios7-close-outline:before{content:"\f2bb"}.ion-ios7-cloud:before{content:"\f178"}.ion-ios7-cloud-download:before{content:"\f174"}.ion-ios7-cloud-download-outline:before{content:"\f173"}.ion-ios7-cloud-outline:before{content:"\f175"}.ion-ios7-cloud-upload:before{content:"\f177"}.ion-ios7-cloud-upload-outline:before{content:"\f176"}.ion-ios7-cloudy:before{content:"\f17a"}.ion-ios7-cloudy-night:before{content:"\f308"}.ion-ios7-cloudy-night-outline:before{content:"\f307"}.ion-ios7-cloudy-outline:before{content:"\f179"}.ion-ios7-cog:before{content:"\f17c"}.ion-ios7-cog-outline:before{content:"\f17b"}.ion-ios7-compose:before{content:"\f17e"}.ion-ios7-compose-outline:before{content:"\f17d"}.ion-ios7-contact:before{content:"\f180"}.ion-ios7-contact-outline:before{content:"\f17f"}.ion-ios7-copy:before{content:"\f182"}.ion-ios7-copy-outline:before{content:"\f181"}.ion-ios7-download:before{content:"\f184"}.ion-ios7-download-outline:before{content:"\f183"}.ion-ios7-drag:before{content:"\f185"}.ion-ios7-email:before{content:"\f187"}.ion-ios7-email-outline:before{content:"\f186"}.ion-ios7-expand:before{content:"\f30d"}.ion-ios7-eye:before{content:"\f189"}.ion-ios7-eye-outline:before{content:"\f188"}.ion-ios7-fastforward:before{content:"\f18b"}.ion-ios7-fastforward-outline:before{content:"\f18a"}.ion-ios7-filing:before{content:"\f18d"}.ion-ios7-filing-outline:before{content:"\f18c"}.ion-ios7-film:before{content:"\f18f"}.ion-ios7-film-outline:before{content:"\f18e"}.ion-ios7-flag:before{content:"\f191"}.ion-ios7-flag-outline:before{content:"\f190"}.ion-ios7-folder:before{content:"\f193"}.ion-ios7-folder-outline:before{content:"\f192"}.ion-ios7-football:before{content:"\f329"}.ion-ios7-football-outline:before{content:"\f328"}.ion-ios7-gear:before{content:"\f195"}.ion-ios7-gear-outline:before{content:"\f194"}.ion-ios7-glasses:before{content:"\f197"}.ion-ios7-glasses-outline:before{content:"\f196"}.ion-ios7-heart:before{content:"\f199"}.ion-ios7-heart-outline:before{content:"\f198"}.ion-ios7-help:before{content:"\f19c"}.ion-ios7-help-empty:before{content:"\f19a"}.ion-ios7-help-outline:before{content:"\f19b"}.ion-ios7-home:before{content:"\f32b"}.ion-ios7-home-outline:before{content:"\f32a"}.ion-ios7-infinite:before{content:"\f19e"}.ion-ios7-infinite-outline:before{content:"\f19d"}.ion-ios7-information:before{content:"\f1a1"}.ion-ios7-information-empty:before{content:"\f19f"}.ion-ios7-information-outline:before{content:"\f1a0"}.ion-ios7-ionic-outline:before{content:"\f1a2"}.ion-ios7-keypad:before{content:"\f1a4"}.ion-ios7-keypad-outline:before{content:"\f1a3"}.ion-ios7-lightbulb:before{content:"\f287"}.ion-ios7-lightbulb-outline:before{content:"\f286"}.ion-ios7-location:before{content:"\f1a6"}.ion-ios7-location-outline:before{content:"\f1a5"}.ion-ios7-locked:before{content:"\f1a8"}.ion-ios7-locked-outline:before{content:"\f1a7"}.ion-ios7-loop:before{content:"\f32d"}.ion-ios7-loop-strong:before{content:"\f32c"}.ion-ios7-medkit:before{content:"\f289"}.ion-ios7-medkit-outline:before{content:"\f288"}.ion-ios7-mic:before{content:"\f1ab"}.ion-ios7-mic-off:before{content:"\f1a9"}.ion-ios7-mic-outline:before{content:"\f1aa"}.ion-ios7-minus:before{content:"\f1ae"}.ion-ios7-minus-empty:before{content:"\f1ac"}.ion-ios7-minus-outline:before{content:"\f1ad"}.ion-ios7-monitor:before{content:"\f1b0"}.ion-ios7-monitor-outline:before{content:"\f1af"}.ion-ios7-moon:before{content:"\f1b2"}.ion-ios7-moon-outline:before{content:"\f1b1"}.ion-ios7-more:before{content:"\f1b4"}.ion-ios7-more-outline:before{content:"\f1b3"}.ion-ios7-musical-note:before{content:"\f1b5"}.ion-ios7-musical-notes:before{content:"\f1b6"}.ion-ios7-navigate:before{content:"\f1b8"}.ion-ios7-navigate-outline:before{content:"\f1b7"}.ion-ios7-paper:before{content:"\f32f"}.ion-ios7-paper-outline:before{content:"\f32e"}.ion-ios7-paperplane:before{content:"\f1ba"}.ion-ios7-paperplane-outline:before{content:"\f1b9"}.ion-ios7-partlysunny:before{content:"\f1bc"}.ion-ios7-partlysunny-outline:before{content:"\f1bb"}.ion-ios7-pause:before{content:"\f1be"}.ion-ios7-pause-outline:before{content:"\f1bd"}.ion-ios7-paw:before{content:"\f331"}.ion-ios7-paw-outline:before{content:"\f330"}.ion-ios7-people:before{content:"\f1c0"}.ion-ios7-people-outline:before{content:"\f1bf"}.ion-ios7-person:before{content:"\f1c2"}.ion-ios7-person-outline:before{content:"\f1c1"}.ion-ios7-personadd:before{content:"\f1c4"}.ion-ios7-personadd-outline:before{content:"\f1c3"}.ion-ios7-photos:before{content:"\f1c6"}.ion-ios7-photos-outline:before{content:"\f1c5"}.ion-ios7-pie:before{content:"\f28b"}.ion-ios7-pie-outline:before{content:"\f28a"}.ion-ios7-play:before{content:"\f1c8"}.ion-ios7-play-outline:before{content:"\f1c7"}.ion-ios7-plus:before{content:"\f1cb"}.ion-ios7-plus-empty:before{content:"\f1c9"}.ion-ios7-plus-outline:before{content:"\f1ca"}.ion-ios7-pricetag:before{content:"\f28d"}.ion-ios7-pricetag-outline:before{content:"\f28c"}.ion-ios7-pricetags:before{content:"\f333"}.ion-ios7-pricetags-outline:before{content:"\f332"}.ion-ios7-printer:before{content:"\f1cd"}.ion-ios7-printer-outline:before{content:"\f1cc"}.ion-ios7-pulse:before{content:"\f335"}.ion-ios7-pulse-strong:before{content:"\f334"}.ion-ios7-rainy:before{content:"\f1cf"}.ion-ios7-rainy-outline:before{content:"\f1ce"}.ion-ios7-recording:before{content:"\f1d1"}.ion-ios7-recording-outline:before{content:"\f1d0"}.ion-ios7-redo:before{content:"\f1d3"}.ion-ios7-redo-outline:before{content:"\f1d2"}.ion-ios7-refresh:before{content:"\f1d6"}.ion-ios7-refresh-empty:before{content:"\f1d4"}.ion-ios7-refresh-outline:before{content:"\f1d5"}.ion-ios7-reload:before{content:"\f28e"}.ion-ios7-reverse-camera:before{content:"\f337"}.ion-ios7-reverse-camera-outline:before{content:"\f336"}.ion-ios7-rewind:before{content:"\f1d8"}.ion-ios7-rewind-outline:before{content:"\f1d7"}.ion-ios7-search:before{content:"\f1da"}.ion-ios7-search-strong:before{content:"\f1d9"}.ion-ios7-settings:before{content:"\f339"}.ion-ios7-settings-strong:before{content:"\f338"}.ion-ios7-shrink:before{content:"\f30e"}.ion-ios7-skipbackward:before{content:"\f1dc"}.ion-ios7-skipbackward-outline:before{content:"\f1db"}.ion-ios7-skipforward:before{content:"\f1de"}.ion-ios7-skipforward-outline:before{content:"\f1dd"}.ion-ios7-snowy:before{content:"\f309"}.ion-ios7-speedometer:before{content:"\f290"}.ion-ios7-speedometer-outline:before{content:"\f28f"}.ion-ios7-star:before{content:"\f1e0"}.ion-ios7-star-half:before{content:"\f33a"}.ion-ios7-star-outline:before{content:"\f1df"}.ion-ios7-stopwatch:before{content:"\f1e2"}.ion-ios7-stopwatch-outline:before{content:"\f1e1"}.ion-ios7-sunny:before{content:"\f1e4"}.ion-ios7-sunny-outline:before{content:"\f1e3"}.ion-ios7-telephone:before{content:"\f1e6"}.ion-ios7-telephone-outline:before{content:"\f1e5"}.ion-ios7-tennisball:before{content:"\f33c"}.ion-ios7-tennisball-outline:before{content:"\f33b"}.ion-ios7-thunderstorm:before{content:"\f1e8"}.ion-ios7-thunderstorm-outline:before{content:"\f1e7"}.ion-ios7-time:before{content:"\f292"}.ion-ios7-time-outline:before{content:"\f291"}.ion-ios7-timer:before{content:"\f1ea"}.ion-ios7-timer-outline:before{content:"\f1e9"}.ion-ios7-toggle:before{content:"\f33e"}.ion-ios7-toggle-outline:before{content:"\f33d"}.ion-ios7-trash:before{content:"\f1ec"}.ion-ios7-trash-outline:before{content:"\f1eb"}.ion-ios7-undo:before{content:"\f1ee"}.ion-ios7-undo-outline:before{content:"\f1ed"}.ion-ios7-unlocked:before{content:"\f1f0"}.ion-ios7-unlocked-outline:before{content:"\f1ef"}.ion-ios7-upload:before{content:"\f1f2"}.ion-ios7-upload-outline:before{content:"\f1f1"}.ion-ios7-videocam:before{content:"\f1f4"}.ion-ios7-videocam-outline:before{content:"\f1f3"}.ion-ios7-volume-high:before{content:"\f1f5"}.ion-ios7-volume-low:before{content:"\f1f6"}.ion-ios7-wineglass:before{content:"\f294"}.ion-ios7-wineglass-outline:before{content:"\f293"}.ion-ios7-world:before{content:"\f1f8"}.ion-ios7-world-outline:before{content:"\f1f7"}.ion-ipad:before{content:"\f1f9"}.ion-iphone:before{content:"\f1fa"}.ion-ipod:before{content:"\f1fb"}.ion-jet:before{content:"\f295"}.ion-key:before{content:"\f296"}.ion-knife:before{content:"\f297"}.ion-laptop:before{content:"\f1fc"}.ion-leaf:before{content:"\f1fd"}.ion-levels:before{content:"\f298"}.ion-lightbulb:before{content:"\f299"}.ion-link:before{content:"\f1fe"}.ion-load-a:before{content:"\f29a"}.ion-load-b:before{content:"\f29b"}.ion-load-c:before{content:"\f29c"}.ion-load-d:before{content:"\f29d"}.ion-location:before{content:"\f1ff"}.ion-locked:before{content:"\f200"}.ion-log-in:before{content:"\f29e"}.ion-log-out:before{content:"\f29f"}.ion-loop:before{content:"\f201"}.ion-magnet:before{content:"\f2a0"}.ion-male:before{content:"\f2a1"}.ion-man:before{content:"\f202"}.ion-map:before{content:"\f203"}.ion-medkit:before{content:"\f2a2"}.ion-merge:before{content:"\f33f"}.ion-mic-a:before{content:"\f204"}.ion-mic-b:before{content:"\f205"}.ion-mic-c:before{content:"\f206"}.ion-minus:before{content:"\f209"}.ion-minus-circled:before{content:"\f207"}.ion-minus-round:before{content:"\f208"}.ion-model-s:before{content:"\f2c1"}.ion-monitor:before{content:"\f20a"}.ion-more:before{content:"\f20b"}.ion-mouse:before{content:"\f340"}.ion-music-note:before{content:"\f20c"}.ion-navicon:before{content:"\f20e"}.ion-navicon-round:before{content:"\f20d"}.ion-navigate:before{content:"\f2a3"}.ion-network:before{content:"\f341"}.ion-no-smoking:before{content:"\f2c2"}.ion-nuclear:before{content:"\f2a4"}.ion-outlet:before{content:"\f342"}.ion-paper-airplane:before{content:"\f2c3"}.ion-paperclip:before{content:"\f20f"}.ion-pause:before{content:"\f210"}.ion-person:before{content:"\f213"}.ion-person-add:before{content:"\f211"}.ion-person-stalker:before{content:"\f212"}.ion-pie-graph:before{content:"\f2a5"}.ion-pin:before{content:"\f2a6"}.ion-pinpoint:before{content:"\f2a7"}.ion-pizza:before{content:"\f2a8"}.ion-plane:before{content:"\f214"}.ion-planet:before{content:"\f343"}.ion-play:before{content:"\f215"}.ion-playstation:before{content:"\f30a"}.ion-plus:before{content:"\f218"}.ion-plus-circled:before{content:"\f216"}.ion-plus-round:before{content:"\f217"}.ion-podium:before{content:"\f344"}.ion-pound:before{content:"\f219"}.ion-power:before{content:"\f2a9"}.ion-pricetag:before{content:"\f2aa"}.ion-pricetags:before{content:"\f2ab"}.ion-printer:before{content:"\f21a"}.ion-pull-request:before{content:"\f345"}.ion-qr-scanner:before{content:"\f346"}.ion-quote:before{content:"\f347"}.ion-radio-waves:before{content:"\f2ac"}.ion-record:before{content:"\f21b"}.ion-refresh:before{content:"\f21c"}.ion-reply:before{content:"\f21e"}.ion-reply-all:before{content:"\f21d"}.ion-ribbon-a:before{content:"\f348"}.ion-ribbon-b:before{content:"\f349"}.ion-sad:before{content:"\f34a"}.ion-scissors:before{content:"\f34b"}.ion-search:before{content:"\f21f"}.ion-settings:before{content:"\f2ad"}.ion-share:before{content:"\f220"}.ion-shuffle:before{content:"\f221"}.ion-skip-backward:before{content:"\f222"}.ion-skip-forward:before{content:"\f223"}.ion-social-android:before{content:"\f225"}.ion-social-android-outline:before{content:"\f224"}.ion-social-apple:before{content:"\f227"}.ion-social-apple-outline:before{content:"\f226"}.ion-social-bitcoin:before{content:"\f2af"}.ion-social-bitcoin-outline:before{content:"\f2ae"}.ion-social-buffer:before{content:"\f229"}.ion-social-buffer-outline:before{content:"\f228"}.ion-social-designernews:before{content:"\f22b"}.ion-social-designernews-outline:before{content:"\f22a"}.ion-social-dribbble:before{content:"\f22d"}.ion-social-dribbble-outline:before{content:"\f22c"}.ion-social-dropbox:before{content:"\f22f"}.ion-social-dropbox-outline:before{content:"\f22e"}.ion-social-facebook:before{content:"\f231"}.ion-social-facebook-outline:before{content:"\f230"}.ion-social-foursquare:before{content:"\f34d"}.ion-social-foursquare-outline:before{content:"\f34c"}.ion-social-freebsd-devil:before{content:"\f2c4"}.ion-social-github:before{content:"\f233"}.ion-social-github-outline:before{content:"\f232"}.ion-social-google:before{content:"\f34f"}.ion-social-google-outline:before{content:"\f34e"}.ion-social-googleplus:before{content:"\f235"}.ion-social-googleplus-outline:before{content:"\f234"}.ion-social-hackernews:before{content:"\f237"}.ion-social-hackernews-outline:before{content:"\f236"}.ion-social-instagram:before{content:"\f351"}.ion-social-instagram-outline:before{content:"\f350"}.ion-social-linkedin:before{content:"\f239"}.ion-social-linkedin-outline:before{content:"\f238"}.ion-social-pinterest:before{content:"\f2b1"}.ion-social-pinterest-outline:before{content:"\f2b0"}.ion-social-reddit:before{content:"\f23b"}.ion-social-reddit-outline:before{content:"\f23a"}.ion-social-rss:before{content:"\f23d"}.ion-social-rss-outline:before{content:"\f23c"}.ion-social-skype:before{content:"\f23f"}.ion-social-skype-outline:before{content:"\f23e"}.ion-social-tumblr:before{content:"\f241"}.ion-social-tumblr-outline:before{content:"\f240"}.ion-social-tux:before{content:"\f2c5"}.ion-social-twitter:before{content:"\f243"}.ion-social-twitter-outline:before{content:"\f242"}.ion-social-usd:before{content:"\f353"}.ion-social-usd-outline:before{content:"\f352"}.ion-social-vimeo:before{content:"\f245"}.ion-social-vimeo-outline:before{content:"\f244"}.ion-social-windows:before{content:"\f247"}.ion-social-windows-outline:before{content:"\f246"}.ion-social-wordpress:before{content:"\f249"}.ion-social-wordpress-outline:before{content:"\f248"}.ion-social-yahoo:before{content:"\f24b"}.ion-social-yahoo-outline:before{content:"\f24a"}.ion-social-youtube:before{content:"\f24d"}.ion-social-youtube-outline:before{content:"\f24c"}.ion-speakerphone:before{content:"\f2b2"}.ion-speedometer:before{content:"\f2b3"}.ion-spoon:before{content:"\f2b4"}.ion-star:before{content:"\f24e"}.ion-stats-bars:before{content:"\f2b5"}.ion-steam:before{content:"\f30b"}.ion-stop:before{content:"\f24f"}.ion-thermometer:before{content:"\f2b6"}.ion-thumbsdown:before{content:"\f250"}.ion-thumbsup:before{content:"\f251"}.ion-toggle:before{content:"\f355"}.ion-toggle-filled:before{content:"\f354"}.ion-trash-a:before{content:"\f252"}.ion-trash-b:before{content:"\f253"}.ion-trophy:before{content:"\f356"}.ion-umbrella:before{content:"\f2b7"}.ion-university:before{content:"\f357"}.ion-unlocked:before{content:"\f254"}.ion-upload:before{content:"\f255"}.ion-usb:before{content:"\f2b8"}.ion-videocamera:before{content:"\f256"}.ion-volume-high:before{content:"\f257"}.ion-volume-low:before{content:"\f258"}.ion-volume-medium:before{content:"\f259"}.ion-volume-mute:before{content:"\f25a"}.ion-wand:before{content:"\f358"}.ion-waterdrop:before{content:"\f25b"}.ion-wifi:before{content:"\f25c"}.ion-wineglass:before{content:"\f2b9"}.ion-woman:before{content:"\f25d"}.ion-wrench:before{content:"\f2ba"}.ion-xbox:before{content:"\f30c"}/*! -Animate.css - http://daneden.me/animate -Version - 3.4.0 -Licensed under the MIT license - http://opensource.org/licenses/MIT - -Copyright (c) 2015 Daniel Eden -*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}.animated.bounceIn,.animated.bounceOut{-webkit-animation-duration:.75s;animation-duration:.75s}.animated.flipOutX,.animated.flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounce{from,20%,53%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{from,20%,53%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{from,50%,to{opacity:1}25%,75%{opacity:0}}@keyframes flash{from,50%,to{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{from{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes pulse{from{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{from{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes rubberBand{from{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{from,to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{from,to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}to{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}@keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}to{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}.swing{-webkit-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{from{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes tada{from{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{from{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}to{-webkit-transform:none;transform:none}}@keyframes wobble{from{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}to{-webkit-transform:none;transform:none}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes jello{from,11.1%,to{-webkit-transform:none;transform:none}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-.78125deg) skewY(-.78125deg);transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{-webkit-transform:skewX(.390625deg) skewY(.390625deg);transform:skewX(.390625deg) skewY(.390625deg)}88.8%{-webkit-transform:skewX(-.1953125deg) skewY(-.1953125deg);transform:skewX(-.1953125deg) skewY(-.1953125deg)}}@keyframes jello{from,11.1%,to{-webkit-transform:none;transform:none}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-.78125deg) skewY(-.78125deg);transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{-webkit-transform:skewX(.390625deg) skewY(.390625deg);transform:skewX(.390625deg) skewY(.390625deg)}88.8%{-webkit-transform:skewX(-.1953125deg) skewY(-.1953125deg);transform:skewX(-.1953125deg) skewY(-.1953125deg)}}.jello{-webkit-animation-name:jello;animation-name:jello;-webkit-transform-origin:center;transform-origin:center}@-webkit-keyframes bounceIn{from,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes bounceIn{from,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceInDown{from,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}to{-webkit-transform:none;transform:none}}@keyframes bounceInDown{from,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}to{-webkit-transform:none;transform:none}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{from,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}to{-webkit-transform:none;transform:none}}@keyframes bounceInLeft{from,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}to{-webkit-transform:none;transform:none}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{from,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}from{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}to{-webkit-transform:none;transform:none}}@keyframes bounceInRight{from,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}from{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}to{-webkit-transform:none;transform:none}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{from,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}from{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes bounceInUp{from,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1.000);animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}from{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}to{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}to{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{from{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDownBig{from{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{from{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeft{from{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{from{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeftBig{from{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{from{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRight{from{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{from{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRightBig{from{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{from{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUp{from{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{from{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUpBig{from{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{from{opacity:1}to{opacity:0}}@keyframes fadeOut{from{opacity:1}to{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{from{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}to{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{from{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}to{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{from{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{from{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{from{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{from{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{from{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}to{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@keyframes flipOutX{from{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}to{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipOutY{from{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}to{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@keyframes flipOutY{from{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}to{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY}@-webkit-keyframes lightSpeedIn{from{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}to{-webkit-transform:none;transform:none;opacity:1}}@keyframes lightSpeedIn{from{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}to{-webkit-transform:none;transform:none;opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{from{opacity:1}to{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}@keyframes lightSpeedOut{from{opacity:1}to{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{from{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}to{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateIn{from{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}to{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{from{-webkit-transform-origin:center;transform-origin:center;opacity:1}to{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}@keyframes rotateOut{from{-webkit-transform-origin:center;transform-origin:center;opacity:1}to{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}@keyframes rotateOutDownLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutDownRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutUpLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}@keyframes rotateOutUpRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}to{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}@keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}to{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{from{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes rollIn{from{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}to{opacity:1;-webkit-transform:none;transform:none}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}@keyframes rollOut{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{from{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{from{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInDown{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInLeft{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInRight{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInUp{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{from{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}@keyframes zoomOut{from{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}@-webkit-keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{from{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInLeft{from{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{from{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInRight{from{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes slideOutLeft{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes slideOutRight{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-number,.hljs-literal,.hljs-variable,.hljs-template-variable,.hljs-tag .hljs-attr{color:teal}.hljs-string,.hljs-doctag{color:#d14}.hljs-title,.hljs-section,.hljs-selector-id{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-type,.hljs-class .hljs-title{color:#458;font-weight:700}.hljs-tag,.hljs-name,.hljs-attribute{color:navy;font-weight:400}.hljs-regexp,.hljs-link{color:#009926}.hljs-symbol,.hljs-bullet{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1.0;-webkit-transform:rotate(3deg) translate(0,-4px);-ms-transform:rotate(3deg) translate(0,-4px);transform:rotate(3deg) translate(0,-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner 400ms linear infinite;animation:nprogress-spinner 400ms linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .spinner,.nprogress-custom-parent #nprogress .bar{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.dropper{overflow:hidden}.dropper,.dropper *,.dropper :before,.dropper :after{box-sizing:border-box}.dropper-dropzone{background:#fff;border:3px dashed #ccc;border-radius:0;color:#666;cursor:pointer;font-size:14px;margin:0;padding:25px;text-align:center}.dropper.dropping .dropper-dropzone,.no-touch .dropper:hover .dropper-dropzone{background:#eee;border-color:#999;color:#333}.dropper-input{position:absolute;left:100%;opacity:0}.no-opacity .dropper-input{left:-999px}/*! jQuery UI - v1.11.4 - 2015-12-12 -* http://jqueryui.com -* Includes: core.css, draggable.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, menu.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px -* Copyright jQuery Foundation and other contributors; Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url(data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==);height:100%;filter:alpha(opacity=25);opacity:.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:700;line-height:1.5;padding:2px .4em;margin:.5em 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:.4em 2.1em .4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:700}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:400;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #ccc;background:#ededed;font-weight:400;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#2b2b2b;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #003eff;background:#007fff;font-weight:400;color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:700}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:400}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_444444_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_444444_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_777777_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_555555_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_777620_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cc0000_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:0;padding:5px;background:#666;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}.md-editor{display:block;border:1px solid #ddd}.md-editor .md-footer,.md-editor>.md-header{display:block;padding:6px 4px;background:#f5f5f5}.md-editor>.md-header{margin:0}.md-editor>.md-preview{background:#fff;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;min-height:10px;overflow:auto}.md-editor>textarea{font-family:Menlo,Monaco,Consolas,Courier New,monospace;font-size:14px;outline:0;margin:0;display:block;padding:0;width:100%;border:0;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;border-radius:0;box-shadow:none;background:#eee}.md-editor>textarea:focus{box-shadow:none;background:#fff}.md-editor.active{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.md-editor .md-controls{float:right;padding:3px}.md-editor .md-controls .md-control{right:5px;color:#bebebe;padding:3px 3px 3px 10px}.md-editor .md-controls .md-control:hover{color:#333}.md-editor.md-fullscreen-mode{width:100%;height:100%;position:fixed;top:0;left:0;z-index:99999;padding:60px 30px 15px;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-footer{display:none}.md-editor.md-fullscreen-mode .md-input,.md-editor.md-fullscreen-mode .md-preview{margin:0 auto!important;height:100%!important;font-size:20px!important;padding:20px!important;color:#999;line-height:1.6em!important;resize:none!important;box-shadow:none!important;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-preview{color:#333;overflow:auto}.md-editor.md-fullscreen-mode .md-input:focus,.md-editor.md-fullscreen-mode .md-input:hover{color:#333;background:#fff!important}.md-editor.md-fullscreen-mode .md-header{background:0 0;text-align:center;position:fixed;width:100%;top:20px}.md-editor.md-fullscreen-mode .btn-group{float:none}.md-editor.md-fullscreen-mode .btn{border:0;background:0 0;color:#b3b3b3}.md-editor.md-fullscreen-mode .btn.active,.md-editor.md-fullscreen-mode .btn:active,.md-editor.md-fullscreen-mode .btn:focus,.md-editor.md-fullscreen-mode .btn:hover{box-shadow:none;color:#333}.md-editor.md-fullscreen-mode .md-fullscreen-controls{position:absolute;top:20px;right:20px;text-align:right;z-index:1002;display:block}.md-editor.md-fullscreen-mode .md-fullscreen-controls a{color:#b3b3b3;clear:right;margin:10px;width:30px;height:30px;text-align:center}.md-editor.md-fullscreen-mode .md-fullscreen-controls a:hover{color:#333;text-decoration:none}.md-editor.md-fullscreen-mode .md-editor{height:100%!important;position:relative}.md-editor .md-fullscreen-controls{display:none}.md-nooverflow{overflow:hidden;position:fixed;width:100%}/*! - * Bootstrap-select v1.10.0 (http://silviomoreto.github.io/bootstrap-select) - * - * Copyright 2013-2016 bootstrap-select - * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE) - */select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px \0}.bootstrap-select>.dropdown-toggle{width:100%;padding-right:25px;z-index:1}.bootstrap-select>.dropdown-toggle.bs-placeholder,.bootstrap-select>.dropdown-toggle.bs-placeholder:hover,.bootstrap-select>.dropdown-toggle.bs-placeholder:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder:active{color:#999}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2}.has-error .bootstrap-select .dropdown-toggle,.error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{z-index:auto}.bootstrap-select.btn-group:not(.input-group-btn),.bootstrap-select.btn-group[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.btn-group.dropdown-menu-right,.bootstrap-select.btn-group[class*=col-].dropdown-menu-right,.row .bootstrap-select.btn-group[class*=col-].dropdown-menu-right{float:right}.form-inline .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group,.form-group .bootstrap-select.btn-group{margin-bottom:0}.form-group-lg .bootstrap-select.btn-group.form-control,.form-group-sm .bootstrap-select.btn-group.form-control{padding:0}.form-inline .bootstrap-select.btn-group .form-control{width:100%}.bootstrap-select.btn-group.disabled,.bootstrap-select.btn-group>.disabled{cursor:not-allowed}.bootstrap-select.btn-group.disabled:focus,.bootstrap-select.btn-group>.disabled:focus{outline:none!important}.bootstrap-select.btn-group.bs-container{position:absolute}.bootstrap-select.btn-group.bs-container .dropdown-menu{z-index:1060}.bootstrap-select.btn-group .dropdown-toggle .filter-option{display:inline-block;overflow:hidden;width:100%;text-align:left}.bootstrap-select.btn-group .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li.active small{color:#fff}.bootstrap-select.btn-group .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select.btn-group .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select.btn-group .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select.btn-group .dropdown-menu li a span.check-mark{display:none}.bootstrap-select.btn-group .dropdown-menu li a span.text{display:inline-block}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.btn-group.fit-width .dropdown-toggle .filter-option{position:static}.bootstrap-select.btn-group.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:5px}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid white;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid white;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after{display:block}.bs-searchbox,.bs-actionsbox,.bs-donebutton{padding:4px 8px}.bs-actionsbox{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%;float:none}/*! -(The MIT License) - -Copyright (c) 2012-2014 Marcin Warpechowski -Copyright (c) 2015 Handsoncode sp. z o.o. - -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. - -*/.handsontable{position:relative}.handsontable .hide{display:none}.handsontable .relative{position:relative}.handsontable.htAutoSize{visibility:hidden;left:-99000px;position:absolute;top:-99000px}.handsontable .wtHider{width:0}.handsontable .wtSpreader{position:relative;width:0;height:auto}.handsontable table,.handsontable tbody,.handsontable thead,.handsontable td,.handsontable th,.handsontable input,.handsontable textarea,.handsontable div{box-sizing:content-box;-webkit-box-sizing:content-box;-moz-box-sizing:content-box}.handsontable input,.handsontable textarea{min-height:initial}.handsontable table.htCore{border-collapse:separate;border-spacing:0;margin:0;border-width:0;table-layout:fixed;width:0;outline-width:0;max-width:none;max-height:none}.handsontable col{width:50px}.handsontable col.rowHeader{width:50px}.handsontable th,.handsontable td{border-top-width:0;border-left-width:0;border-right:1px solid #CCC;border-bottom:1px solid #CCC;height:22px;empty-cells:show;line-height:21px;padding:0 4px;background-color:#FFF;vertical-align:top;overflow:hidden;outline-width:0;white-space:pre-line}.handsontable td.htInvalid{background-color:#ff4c42!important}.handsontable td.htNoWrap{white-space:nowrap}.handsontable th:last-child{border-right:1px solid #CCC;border-bottom:1px solid #CCC}.handsontable tr:first-child th.htNoFrame,.handsontable th:first-child.htNoFrame,.handsontable th.htNoFrame{border-left-width:0;background-color:white;border-color:#FFF}.handsontable th:first-child,.handsontable td:first-of-type,.handsontable .htNoFrame+th,.handsontable .htNoFrame+td{border-left:1px solid #CCC}.handsontable.htRowHeaders thead tr th:nth-child(2){border-left:1px solid #CCC}.handsontable tr:first-child th,.handsontable tr:first-child td{border-top:1px solid #CCC}.ht_master:not(.innerBorderLeft)~.handsontable tbody tr th,.ht_master:not(.innerBorderLeft)~.handsontable:not(.ht_clone_top) thead tr th:first-child{border-right-width:0}.ht_master:not(.innerBorderTop) thead tr:last-child th,.ht_master:not(.innerBorderTop)~.handsontable thead tr:last-child th,.ht_master:not(.innerBorderTop) thead tr.lastChild th,.ht_master:not(.innerBorderTop)~.handsontable thead tr.lastChild th{border-bottom-width:0}.handsontable th{background-color:#EEE;color:#222;text-align:center;font-weight:400;white-space:nowrap}.handsontable thead th{padding:0}.handsontable th.active{background-color:#CCC}.handsontable thead th .relative{padding:2px 4px}.handsontable .manualColumnMover{position:fixed;left:0;top:0;background-color:transparent;width:5px;height:25px;z-index:999;cursor:move}.handsontable .manualRowMover{position:fixed;left:-4px;top:0;background-color:transparent;height:5px;width:50px;z-index:999;cursor:move}.handsontable .manualColumnMoverGuide,.handsontable .manualRowMoverGuide{position:fixed;left:0;top:0;background-color:#CCC;width:25px;height:25px;opacity:.7;display:none}.handsontable .manualColumnMoverGuide.active,.handsontable .manualRowMoverGuide.active{display:block}.handsontable .manualColumnMover:hover,.handsontable .manualColumnMover.active,.handsontable .manualRowMover:hover,.handsontable .manualRowMover.active{background-color:#88F}.handsontable .manualColumnResizer{position:fixed;top:0;cursor:col-resize;z-index:110;width:5px;height:25px}.handsontable .manualRowResizer{position:fixed;left:0;cursor:row-resize;z-index:110;height:5px;width:50px}.handsontable .manualColumnResizer:hover,.handsontable .manualColumnResizer.active,.handsontable .manualRowResizer:hover,.handsontable .manualRowResizer.active{background-color:#AAB}.handsontable .manualColumnResizerGuide{position:fixed;right:0;top:0;background-color:#AAB;display:none;width:0;border-right:1px dashed #777;margin-left:5px}.handsontable .manualRowResizerGuide{position:fixed;left:0;bottom:0;background-color:#AAB;display:none;height:0;border-bottom:1px dashed #777;margin-top:5px}.handsontable .manualColumnResizerGuide.active,.handsontable .manualRowResizerGuide.active{display:block}.handsontable .columnSorting{position:relative}.handsontable .columnSorting:hover{text-decoration:underline;cursor:pointer}.handsontable .columnSorting.ascending::after{content:'\25B2';color:#5f5f5f;position:absolute;right:-15px}.handsontable .columnSorting.descending::after{content:'\25BC';color:#5f5f5f;position:absolute;right:-15px}.handsontable th.beforeHiddenColumn{position:relative}.handsontable th.beforeHiddenColumn::after,.handsontable th.afterHiddenColumn::before{content:'\25C0';color:#bbb;position:absolute;right:1px;top:2px;font-size:5pt}.handsontable th.afterHiddenColumn{position:relative}.handsontable th.afterHiddenColumn::before{left:1px;top:2px;right:auto;content:'\25B6'}.handsontable td.afterHiddenColumn.firstVisible{border-left:1px solid #CCC}.handsontable thead th.hiddenHeader{display:none}.handsontable .wtBorder{position:absolute;font-size:0}.handsontable .wtBorder.hidden{display:none!important}.handsontable td.area{background:-moz-linear-gradient(top,rgba(181,209,255,.34) 0,rgba(181,209,255,.34) 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,rgba(181,209,255,.34)),color-stop(100%,rgba(181,209,255,.34)));background:-webkit-linear-gradient(top,rgba(181,209,255,.34) 0,rgba(181,209,255,.34) 100%);background:-o-linear-gradient(top,rgba(181,209,255,.34) 0,rgba(181,209,255,.34) 100%);background:-ms-linear-gradient(top,rgba(181,209,255,.34) 0,rgba(181,209,255,.34) 100%);background:linear-gradient(to bottom,rgba(181,209,255,.34) 0,rgba(181,209,255,.34) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#57b5d1ff',endColorstr='#57b5d1ff',GradientType=0);background-color:#fff}.handsontable .wtBorder.corner{font-size:0;cursor:crosshair}.handsontable .htBorder.htFillBorder{background:red;width:1px;height:1px}.handsontableInput{border:0;outline-width:0;margin:0;padding:1px 5px 0;font-family:inherit;line-height:21px;font-size:inherit;box-shadow:0 0 0 2px #5292f7 inset;resize:none;display:inline-block;color:#000;border-radius:0;background-color:#FFF}.handsontableInputHolder{position:absolute;top:0;left:0;z-index:100}.htSelectEditor{-webkit-appearance:menulist-button!important;position:absolute;width:auto}.handsontable .htDimmed{color:#777}.handsontable .htSubmenu{position:relative}.handsontable .htSubmenu :after{content:'▶';color:#777;position:absolute;right:5px}.handsontable .htLeft{text-align:left}.handsontable .htCenter{text-align:center}.handsontable .htRight{text-align:right}.handsontable .htJustify{text-align:justify}.handsontable .htTop{vertical-align:top}.handsontable .htMiddle{vertical-align:middle}.handsontable .htBottom{vertical-align:bottom}.handsontable .htPlaceholder{color:#999}.handsontable .htAutocompleteArrow{float:right;font-size:10px;color:#EEE;cursor:default;width:16px;text-align:center}.handsontable td .htAutocompleteArrow:hover{color:#777}.handsontable td.area .htAutocompleteArrow{color:#d3d3d3}.handsontable .htCheckboxRendererInput.noValue{opacity:.5}.handsontable .htCheckboxRendererLabel{cursor:pointer;display:inline-block;width:100%}.handsontable .htNumeric{text-align:right}.htCommentCell{position:relative}.htCommentCell:after{content:'';position:absolute;top:0;right:0;border-left:6px solid transparent;border-top:6px solid red}@-webkit-keyframes opacity-hide{from{opacity:1}to{opacity:0}}@keyframes opacity-hide{from{opacity:1}to{opacity:0}}@-webkit-keyframes opacity-show{from{opacity:0}to{opacity:1}}@keyframes opacity-show{from{opacity:0}to{opacity:1}}.handsontable .handsontable.ht_clone_top .wtHider{padding:0 0 5px}.handsontable .autocompleteEditor.handsontable{padding-right:17px}.handsontable .autocompleteEditor.handsontable.htMacScroll{padding-right:15px}.handsontable.listbox{margin:0}.handsontable.listbox .ht_master table{border:1px solid #ccc;border-collapse:separate;background:white}.handsontable.listbox th,.handsontable.listbox tr:first-child th,.handsontable.listbox tr:last-child th,.handsontable.listbox tr:first-child td,.handsontable.listbox td{border-color:transparent}.handsontable.listbox th,.handsontable.listbox td{white-space:nowrap;text-overflow:ellipsis}.handsontable.listbox td.htDimmed{cursor:default;color:inherit;font-style:inherit}.handsontable.listbox .wtBorder{visibility:hidden}.handsontable.listbox tr td.current,.handsontable.listbox tr:hover td{background:#eee}.ht_clone_top{z-index:101}.ht_clone_left{z-index:102}.ht_clone_top_left_corner,.ht_clone_bottom_left_corner{z-index:103}.ht_clone_debug{z-index:103}.handsontable td.htSearchResult{background:#fcedd9;color:#583707}.htBordered{border-width:1px}.htBordered.htTopBorderSolid{border-top-style:solid;border-top-color:#000}.htBordered.htRightBorderSolid{border-right-style:solid;border-right-color:#000}.htBordered.htBottomBorderSolid{border-bottom-style:solid;border-bottom-color:#000}.htBordered.htLeftBorderSolid{border-left-style:solid;border-left-color:#000}.htCommentTextArea{-moz-box-shadow:1px 1px 2px #bbb;-webkit-box-shadow:1px 1px 2px #bbb;background-color:#fffacd;border:1px solid #999;box-shadow:1px 1px 2px #bbb;font-family:Arial}.handsontable tbody tr th:nth-last-child(2){border-right:1px solid #CCC}.handsontable thead tr:nth-last-child(2) th.htGroupIndicatorContainer{border-bottom:1px solid #CCC;padding-bottom:5px}.ht_clone_top_left_corner thead tr th:nth-last-child(2){border-right:1px solid #CCC}.htCollapseButton{width:10px;height:10px;line-height:10px;text-align:center;border-radius:5px;border:1px solid #f3f3f3;-webkit-box-shadow:1px 1px 3px rgba(0,0,0,.4);box-shadow:1px 1px 3px rgba(0,0,0,.4);cursor:pointer;margin-bottom:3px;position:relative}.htCollapseButton:after{content:"";height:300%;width:1px;display:block;background:#ccc;margin-left:4px;position:absolute;bottom:10px}thead .htCollapseButton{right:5px;position:absolute;top:5px;background:#fff}thead .htCollapseButton:after{height:1px;width:700%;right:10px;top:4px}.handsontable tr th .htExpandButton{position:absolute;width:10px;height:10px;line-height:10px;text-align:center;border-radius:5px;border:1px solid #f3f3f3;-webkit-box-shadow:1px 1px 3px rgba(0,0,0,.4);box-shadow:1px 1px 3px rgba(0,0,0,.4);cursor:pointer;top:0;display:none}.handsontable thead tr th .htExpandButton{top:5px}.handsontable tr th .htExpandButton.clickable{display:block}.collapsibleIndicator{position:absolute;top:50%;transform:translate(0,-50%);right:5px;border:1px solid #a6a6a6;line-height:10px;color:#222;border-radius:10px;font-size:10px;width:10px;height:10px;cursor:pointer;-webkit-box-shadow:0 0 0 6px #eee;-moz-box-shadow:0 0 0 6px #eee;box-shadow:0 0 0 6px #eee;background:#eee}.handsontable col.hidden{width:0!important}.handsontable table tr th.lightRightBorder{border-right:1px solid #e6e6e6}.handsontable tr.hidden,.handsontable tr.hidden td,.handsontable tr.hidden th{display:none}.ht_master,.ht_clone_left,.ht_clone_top,.ht_clone_bottom{overflow:hidden}.ht_master .wtHolder{overflow:auto}.ht_clone_left .wtHolder{overflow-x:hidden;overflow-y:auto}.ht_clone_top .wtHolder,.ht_clone_bottom .wtHolder{overflow-x:auto;overflow-y:hidden}.wtDebugHidden{display:none}.wtDebugVisible{display:block;-webkit-animation-duration:.5s;-webkit-animation-name:wtFadeInFromNone;animation-duration:.5s;animation-name:wtFadeInFromNone}@keyframes wtFadeInFromNone{0%{display:none;opacity:0}1%{display:block;opacity:0}100%{display:block;opacity:1}}@-webkit-keyframes wtFadeInFromNone{0%{display:none;opacity:0}1%{display:block;opacity:0}100%{display:block;opacity:1}}.handsontable.mobile,.handsontable.mobile .wtHolder{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-overflow-scrolling:touch}.htMobileEditorContainer{display:none;position:absolute;top:0;width:70%;height:54pt;background:#f8f8f8;border-radius:20px;border:1px solid #ebebeb;z-index:999;box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-text-size-adjust:none}.topLeftSelectionHandle:not(.ht_master .topLeftSelectionHandle),.topLeftSelectionHandle-HitArea:not(.ht_master .topLeftSelectionHandle-HitArea){z-index:9999}.topLeftSelectionHandle,.topLeftSelectionHandle-HitArea,.bottomRightSelectionHandle,.bottomRightSelectionHandle-HitArea{left:-10000px;top:-10000px}.htMobileEditorContainer.active{display:block}.htMobileEditorContainer .inputs{position:absolute;right:210pt;bottom:10pt;top:10pt;left:14px;height:34pt}.htMobileEditorContainer .inputs textarea{font-size:13pt;border:1px solid #a1a1a1;-webkit-appearance:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;position:absolute;left:14px;right:14px;top:0;bottom:0;padding:7pt}.htMobileEditorContainer .cellPointer{position:absolute;top:-13pt;height:0;width:0;left:30px;border-left:13pt solid transparent;border-right:13pt solid transparent;border-bottom:13pt solid #ebebeb}.htMobileEditorContainer .cellPointer.hidden{display:none}.htMobileEditorContainer .cellPointer:before{content:'';display:block;position:absolute;top:2px;height:0;width:0;left:-13pt;border-left:13pt solid transparent;border-right:13pt solid transparent;border-bottom:13pt solid #f8f8f8}.htMobileEditorContainer .moveHandle{position:absolute;top:10pt;left:5px;width:30px;bottom:0;cursor:move;z-index:9999}.htMobileEditorContainer .moveHandle:after{content:"..\a..\a..\a..";white-space:pre;line-height:10px;font-size:20pt;display:inline-block;margin-top:-8px;color:#ebebeb}.htMobileEditorContainer .positionControls{width:205pt;position:absolute;right:5pt;top:0;bottom:0}.htMobileEditorContainer .positionControls>div{width:50pt;height:100%;float:left}.htMobileEditorContainer .positionControls>div:after{content:" ";display:block;width:15pt;height:15pt;text-align:center;line-height:50pt}.htMobileEditorContainer .leftButton:after,.htMobileEditorContainer .rightButton:after,.htMobileEditorContainer .upButton:after,.htMobileEditorContainer .downButton:after{transform-origin:5pt 5pt;-webkit-transform-origin:5pt 5pt;margin:21pt 0 0 21pt}.htMobileEditorContainer .leftButton:after{border-top:2px solid #288ffe;border-left:2px solid #288ffe;-webkit-transform:rotate(-45deg)}.htMobileEditorContainer .leftButton:active:after{border-color:#cfcfcf}.htMobileEditorContainer .rightButton:after{border-top:2px solid #288ffe;border-left:2px solid #288ffe;-webkit-transform:rotate(135deg)}.htMobileEditorContainer .rightButton:active:after{border-color:#cfcfcf}.htMobileEditorContainer .upButton:after{border-top:2px solid #288ffe;border-left:2px solid #288ffe;-webkit-transform:rotate(45deg)}.htMobileEditorContainer .upButton:active:after{border-color:#cfcfcf}.htMobileEditorContainer .downButton:after{border-top:2px solid #288ffe;border-left:2px solid #288ffe;-webkit-transform:rotate(225deg)}.htMobileEditorContainer .downButton:active:after{border-color:#cfcfcf}.handsontable.hide-tween{-webkit-animation:opacity-hide .3s;animation:opacity-hide .3s;animation-fill-mode:forwards;-webkit-animation-fill-mode:forwards}.handsontable.show-tween{-webkit-animation:opacity-show .3s;animation:opacity-show .3s;animation-fill-mode:forwards;-webkit-animation-fill-mode:forwards}/*! - * Handsontable ContextMenu - */.htContextMenu{display:none;position:absolute;z-index:1060}.htContextMenu .ht_clone_top,.htContextMenu .ht_clone_left,.htContextMenu .ht_clone_corner,.htContextMenu .ht_clone_debug{display:none}.htContextMenu table.htCore{border:1px solid #bbb;border-bottom-width:2px;border-right-width:2px}.htContextMenu .wtBorder{visibility:hidden}.htContextMenu table tbody tr td{background:white;border-width:0;padding:4px 6px 0;cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.htContextMenu table tbody tr td:first-child{border:0}.htContextMenu table tbody tr td.htDimmed{font-style:normal;color:#323232}.htContextMenu table tbody tr td.current,.htContextMenu table tbody tr td.zeroclipboard-is-hover{background:#e9e9e9}.htContextMenu table tbody tr td.htSeparator{border-top:1px solid #bbb;height:0;padding:0;cursor:default}.htContextMenu table tbody tr td.htDisabled{color:#999}.htContextMenu table tbody tr td.htDisabled:hover{background:#fff;color:#999;cursor:default}.htContextMenu table tbody tr.htHidden{display:none}.htContextMenu table tbody tr td .htItemWrapper{margin-left:10px;margin-right:6px}.htContextMenu table tbody tr td div span.selected{margin-top:-2px;position:absolute;left:4px}.htContextMenu .ht_master .wtHolder{overflow:hidden}/*! - * Pikaday - * Copyright © 2014 David Bushell | BSD & MIT license | http://dbushell.com/ - */.pika-single{z-index:9999;display:block;position:relative;color:#333;background:#fff;border:1px solid #ccc;border-bottom-color:#bbb;font-family:Helvetica Neue,Helvetica,Arial,sans-serif}.pika-single:before,.pika-single:after{content:" ";display:table}.pika-single:after{clear:both}.pika-single{zoom:1}.pika-single.is-hidden{display:none}.pika-single.is-bound{position:absolute;box-shadow:0 5px 15px -5px rgba(0,0,0,.5)}.pika-lendar{float:left;width:240px;margin:8px}.pika-title{position:relative;text-align:center}.pika-label{display:inline-block;display:inline;position:relative;z-index:9999;overflow:hidden;margin:0;padding:5px 3px;font-size:14px;line-height:20px;font-weight:700;background-color:#fff}.pika-title select{cursor:pointer;position:absolute;z-index:9998;margin:0;left:0;top:5px;filter:alpha(opacity=0);opacity:0}.pika-prev,.pika-next{display:block;cursor:pointer;position:relative;outline:0;border:0;padding:0;width:20px;height:30px;text-indent:20px;white-space:nowrap;overflow:hidden;background-color:transparent;background-position:center center;background-repeat:no-repeat;background-size:75% 75%;opacity:.5;position:absolute;top:0}.pika-prev:hover,.pika-next:hover{opacity:1}.pika-prev,.is-rtl .pika-next{float:left;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg==);left:0}.pika-next,.is-rtl .pika-prev{float:right;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII=);right:0}.pika-prev.is-disabled,.pika-next.is-disabled{cursor:default;opacity:.2}.pika-select{display:inline-block;display:inline}.pika-table{width:100%;border-collapse:collapse;border-spacing:0;border:0}.pika-table th,.pika-table td{width:14.285714285714286%;padding:0}.pika-table th{color:#999;font-size:12px;line-height:25px;font-weight:700;text-align:center}.pika-button{cursor:pointer;display:block;box-sizing:border-box;-moz-box-sizing:border-box;outline:0;border:0;margin:0;width:100%;padding:5px;color:#666;font-size:12px;line-height:15px;text-align:right;background:#f5f5f5}.pika-week{font-size:11px;color:#999}.is-today .pika-button{color:#3af;font-weight:700}.is-selected .pika-button{color:#fff;font-weight:700;background:#3af;box-shadow:inset 0 1px 3px #178fe5;border-radius:3px}.is-inrange .pika-button{background:#d5e9f7}.is-startrange .pika-button{color:#fff;background:#6cb31d;box-shadow:none;border-radius:3px}.is-endrange .pika-button{color:#fff;background:#3af;box-shadow:none;border-radius:3px}.is-disabled .pika-button{pointer-events:none;cursor:default;color:#999;opacity:.3}.pika-button:hover{color:#fff;background:#ff8000;box-shadow:none;border-radius:3px}.pika-table abbr{border-bottom:0;cursor:help}.tag-editor{list-style-type:none;padding:0 5px 0 0;margin:0;overflow:hidden;border:1px solid #eee;cursor:text;font:normal 14px sans-serif;color:#555;background:#fff}.tag-editor li{display:block;float:left;overflow:hidden;margin:3px 0;line-height:1.5}.tag-editor div{float:left;padding:0 4px}.tag-editor .placeholder{padding:0 8px;color:#bbb}.tag-editor .tag-editor-spacer{padding:0;width:8px;overflow:hidden;color:transparent;background:none}.tag-editor input{vertical-align:inherit;border:0;outline:none;padding:0;margin:0;cursor:text;font-family:inherit;font-weight:inherit;font-size:inherit;font-style:inherit;box-shadow:none;background:none}.tag-editor-hidden-src{position:absolute!important;left:-99999px}.tag-editor ::-ms-clear{display:none}.tag-editor .tag-editor-tag{padding-left:5px;color:#46799b;background:#e0eaf1;white-space:nowrap;overflow:hidden;cursor:pointer;border-radius:2px 0 0 2px}.tag-editor .tag-editor-delete{background:#e0eaf1;cursor:pointer;border-radius:0 2px 2px 0;padding-left:3px;padding-right:4px}.tag-editor .tag-editor-delete i:before{display:inline-block;line-height:20px;font-size:16px;color:#8ba7ba;content:"×"}.tag-editor .tag-editor-delete:hover i:before{color:#d65454}.tag-editor .tag-editor-tag.active+.tag-editor-delete,.tag-editor .tag-editor-tag.active+.tag-editor-delete i{visibility:hidden;cursor:text}.tag-editor .tag-editor-tag.active{background:none!important}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default;font-size:14px}.ui-front{z-index:9999}.ui-menu{list-style:none;padding:1px;margin:0;display:block;outline:none}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.4;min-height:0}.ui-widget-content{border:1px solid #bbb;background:#fff;color:#555}.ui-widget-content a{color:#46799b}.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{background:#e0eaf1}.ui-helper-hidden-accessible{display:none}/*! - * Social Share Kit v1.0.3 (http://socialsharekit.com) - * Copyright 2015 Social Share Kit / Kaspars Sprogis. - * Licensed under Creative Commons Attribution-NonCommercial 3.0 license: - * https://github.com/darklow/social-share-kit/blob/master/LICENSE - * --- - */@font-face{font-family:social-share-kit;src:url(../fonts/social-share-kit.eot);src:url(../fonts/social-share-kit.eot?#iefix) format('embedded-opentype'),url(../fonts/social-share-kit.woff) format('woff'),url(../fonts/social-share-kit.ttf) format('truetype'),url(../fonts/social-share-kit.svg#social-share-kit) format('svg')}.ssk:before{display:inline-block;font-family:social-share-kit!important;font-style:normal!important;font-weight:400!important;font-variant:normal!important;text-transform:none!important;speak:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ssk-facebook:before{content:"a";text-indent:4px;margin-right:-4px}.ssk-twitter:before{content:"b"}.ssk-google-plus:before{content:"c"}.ssk-email:before{content:"d";top:-1px;position:relative}.ssk-pinterest:before{content:"e"}.ssk-tumblr:before{content:"f"}.ssk-linkedin:before{content:"g"}.ssk-github:before{content:"h"}.ssk-vk:before{content:"i"}.ssk-instagram:before{content:"j"}.ssk-amazon:before{content:"k"}.ssk-skype:before{content:"s"}.ssk-youtube:before{content:"x"}.ssk-vimeo:before{content:"u"}.ssk-ebay:before{content:"p"}.ssk-apple:before{content:"l"}.ssk-behance:before{content:"q"}.ssk-dribble:before{content:"n"}.ssk-android:before{content:"o"}.ssk-whatsapp:before{content:"m"}.ssk-reddit:before{content:"r"}.ssk-reddit2:before{content:"t"}.ssk{background-color:#757575;color:white;display:inline-block;font-size:22px;line-height:1px;margin-right:2px;margin-bottom:2px;padding:7px;text-align:center;text-decoration:none;transition:background-color .1s;-webkit-transition:background-color .1s;-moz-transition:background-color .1s;-ms-transition:background-color .1s;-o-transition:background-color .1s}.ssk:before,.ssk .glyphicon,.ssk .fa{position:relative;font-size:22px;top:0;vertical-align:middle}.ssk.ssk-xs,.ssk-xs>.ssk{padding:4px}.ssk.ssk-xs:before,.ssk-xs>.ssk:before,.ssk.ssk-xs .glyphicon,.ssk-xs>.ssk .glyphicon,.ssk.ssk-xs .fa,.ssk-xs>.ssk .fa{font-size:15px}.ssk.ssk-sm,.ssk-sm>.ssk{padding:5px}.ssk.ssk-sm:before,.ssk-sm>.ssk:before,.ssk.ssk-sm .glyphicon,.ssk-sm>.ssk .glyphicon,.ssk.ssk-sm .fa,.ssk-sm>.ssk .fa{font-size:20px}.ssk.ssk-lg,.ssk-lg>.ssk{padding:9px}.ssk.ssk-lg:before,.ssk-lg>.ssk:before,.ssk.ssk-lg .glyphicon,.ssk-lg>.ssk .glyphicon,.ssk.ssk-lg .fa,.ssk-lg>.ssk .fa{font-size:28px}.ssk:last-child{margin-right:0}.ssk:hover{background-color:#424242}.ssk:hover,.ssk:focus{color:#fff;text-decoration:none}.ssk.ssk-round,.ssk-round .ssk{border-radius:50%}.ssk.ssk-round:before,.ssk-round .ssk:before{text-indent:0;margin-right:0}.ssk.ssk-rounded,.ssk-rounded .ssk{border-radius:15%}.ssk.ssk-icon{color:#757575;padding:2px;font-size:24px}.ssk.ssk-icon,.ssk.ssk-icon:hover{background-color:transparent}.ssk.ssk-icon:hover{color:#424242}.ssk.ssk-icon.ssk-xs,.ssk-xs>.ssk.ssk-icon{font-size:16px}.ssk.ssk-icon.ssk-sm,.ssk-sm>.ssk.ssk-icon{font-size:20px}.ssk.ssk-icon.ssk-lg,.ssk-lg>.ssk.ssk-icon{font-size:28px}.ssk.ssk-text{overflow:hidden;font-size:17px;line-height:normal;padding-right:10px}.ssk.ssk-text:before,.ssk.ssk-text .glyphicon,.ssk.ssk-text .fa{margin:-7px 10px -7px -7px;padding:7px;background-color:rgba(0,0,0,.15);vertical-align:bottom;text-indent:0}.ssk-block .ssk.ssk-text{display:block;margin-right:0;text-align:left}.ssk.ssk-text.ssk-xs,.ssk-xs>.ssk.ssk-text{font-size:12px;padding-right:6px}.ssk.ssk-text.ssk-xs:before,.ssk-xs>.ssk.ssk-text:before,.ssk.ssk-text.ssk-xs .glyphicon,.ssk-xs>.ssk.ssk-text .glyphicon,.ssk.ssk-text.ssk-xs .fa,.ssk-xs>.ssk.ssk-text .fa{margin:-4px 6px -4px -4px;padding:4px}.ssk.ssk-text.ssk-sm,.ssk-sm>.ssk.ssk-text{font-size:16px;padding-right:7px}.ssk.ssk-text.ssk-sm:before,.ssk-sm>.ssk.ssk-text:before,.ssk.ssk-text.ssk-sm .glyphicon,.ssk-sm>.ssk.ssk-text .glyphicon,.ssk.ssk-text.ssk-sm .fa,.ssk-sm>.ssk.ssk-text .fa{margin:-5px 7px -5px -5px;padding:5px}.ssk.ssk-text.ssk-lg,.ssk-lg>.ssk.ssk-text{font-size:22px;padding-right:13px}.ssk.ssk-text.ssk-lg:before,.ssk-lg>.ssk.ssk-text:before,.ssk.ssk-text.ssk-lg .glyphicon,.ssk-lg>.ssk.ssk-text .glyphicon,.ssk.ssk-text.ssk-lg .fa,.ssk-lg>.ssk.ssk-text .fa{margin:-9px 13px -9px -9px;padding:9px}.ssk-group,.ssk-sticky{font-size:0}.ssk-sticky{top:0;position:fixed;z-index:2000}.ssk-sticky .ssk{transition:padding .1s ease-out;-webkit-transition:padding .1s ease-out;-moz-transition:padding .1s ease-out;-ms-transition:padding .1s ease-out;-o-transition:padding .1s ease-out;margin:0}.ssk-sticky.ssk-left .ssk,.ssk-sticky.ssk-right .ssk{display:block;clear:both}.ssk-sticky.ssk-left.ssk-center,.ssk-sticky.ssk-right.ssk-center{top:50%;transform:translateY(-50%);-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%)}.ssk-sticky.ssk-left{left:0}.ssk-sticky.ssk-left .ssk{float:left}.ssk-sticky.ssk-left .ssk:hover{padding-left:15px}.ssk-sticky.ssk-right{right:0}.ssk-sticky.ssk-right .ssk{float:right}.ssk-sticky.ssk-right .ssk:hover{padding-right:15px}.ssk-sticky.ssk-bottom{font-size:0;top:auto;bottom:0}.ssk-sticky.ssk-bottom.ssk-center{left:50%;right:auto;transform:translateX(-50%);-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-ms-transform:translateX(-50%);-o-transform:translateX(-50%)}.ssk-sticky.ssk-bottom .ssk{vertical-align:bottom}.ssk-sticky.ssk-bottom .ssk:hover{padding-bottom:15px}.ssk-sticky.ssk-round.ssk-xs .ssk:hover{padding:8px}.ssk-sticky.ssk-round.ssk-sm .ssk:hover{padding:9px}.ssk-sticky.ssk-round .ssk:hover{padding:11px}.ssk-sticky.ssk-round.ssk-lg .ssk:hover{padding:13px}@media(max-width:767px){.ssk-sticky{display:none}}.ssk-count{padding-top:20px}.ssk-count .ssk{position:relative}.ssk-count .ssk-num{border-radius:4px;color:#8f8f8f;background-color:rgba(50,50,50,.03);display:block;font-size:12px;left:0;line-height:20px;position:absolute;right:0;text-align:center;top:-20px}.ssk-count.ssk-sticky{padding-top:0}.ssk-count.ssk-sticky.ssk-left .ssk-num,.ssk-count.ssk-sticky.ssk-right .ssk-num{top:20%;background-color:transparent}.ssk-count.ssk-sticky.ssk-left .ssk-num{left:100%;margin-left:5px}.ssk-count.ssk-sticky.ssk-right .ssk-num{right:115%;margin-left:-100%;text-align:right}.ssk-facebook{background-color:#255c95}.ssk-grayscale>.ssk-facebook{background-color:#757575}.ssk-facebook:hover{background-color:#1b436c}.ssk-facebook:hover{background-color:#1b436c}.ssk-grayscale>.ssk-facebook:hover{background-color:#255c95}.ssk-facebook.ssk-icon{color:#255c95}.ssk-facebook.ssk-icon:hover{color:#1b436c}.ssk-facebook.ssk-icon:before{text-indent:0;margin-right:0}.ssk-twitter{background-color:#00b4e0}.ssk-grayscale>.ssk-twitter{background-color:#757575}.ssk-twitter:hover{background-color:#008bad}.ssk-twitter:hover{background-color:#008bad}.ssk-grayscale>.ssk-twitter:hover{background-color:#00b4e0}.ssk-twitter.ssk-icon{color:#00b4e0}.ssk-twitter.ssk-icon:hover{color:#008bad}.ssk-google-plus{background-color:#f1403a}.ssk-grayscale>.ssk-google-plus{background-color:#757575}.ssk-google-plus:hover{background-color:#e81810}.ssk-google-plus:hover{background-color:#e81810}.ssk-grayscale>.ssk-google-plus:hover{background-color:#f1403a}.ssk-google-plus.ssk-icon{color:#f1403a}.ssk-google-plus.ssk-icon:hover{color:#e81810}.ssk-pinterest{background-color:#cb2027}.ssk-grayscale>.ssk-pinterest{background-color:#757575}.ssk-pinterest:hover{background-color:#9f191f}.ssk-pinterest:hover{background-color:#9f191f}.ssk-grayscale>.ssk-pinterest:hover{background-color:#cb2027}.ssk-pinterest.ssk-icon{color:#cb2027}.ssk-pinterest.ssk-icon:hover{color:#9f191f}.ssk-tumblr{background-color:#395773}.ssk-grayscale>.ssk-tumblr{background-color:#757575}.ssk-tumblr:hover{background-color:#283d51}.ssk-tumblr:hover{background-color:#283d51}.ssk-grayscale>.ssk-tumblr:hover{background-color:#395773}.ssk-tumblr.ssk-icon{color:#395773}.ssk-tumblr.ssk-icon:hover{color:#283d51}.ssk-email{background-color:#757575}.ssk-grayscale>.ssk-email{background-color:#757575}.ssk-email:hover{background-color:#5b5b5b}.ssk-email:hover{background-color:#5b5b5b}.ssk-grayscale>.ssk-email:hover{background-color:#757575}.ssk-grayscale>.ssk-email:hover{background-color:#5b5b5b}.ssk-email.ssk-icon{color:#757575}.ssk-email.ssk-icon:hover{color:#5b5b5b}.ssk-vk{background-color:#54769a}.ssk-grayscale>.ssk-vk{background-color:#757575}.ssk-vk:hover{background-color:#425d79}.ssk-vk:hover{background-color:#425d79}.ssk-grayscale>.ssk-vk:hover{background-color:#54769a}.ssk-vk.ssk-icon{color:#54769a}.ssk-vk.ssk-icon:hover{color:#425d79}.ssk-linkedin{background-color:#1c87bd}.ssk-grayscale>.ssk-linkedin{background-color:#757575}.ssk-linkedin:hover{background-color:#156791}.ssk-linkedin:hover{background-color:#156791}.ssk-grayscale>.ssk-linkedin:hover{background-color:#1c87bd}.ssk-linkedin.ssk-icon{color:#1c87bd}.ssk-linkedin.ssk-icon:hover{color:#156791}.ssk-whatsapp{background-color:#34af23}.ssk-grayscale>.ssk-whatsapp{background-color:#757575}.ssk-whatsapp:hover{background-color:#27851a}.ssk-whatsapp:hover{background-color:#27851a}.ssk-grayscale>.ssk-whatsapp:hover{background-color:#34af23}.ssk-whatsapp.ssk-icon{color:#34af23}.ssk-whatsapp.ssk-icon:hover{color:#27851a}.ssk-reddit{background-color:#5f99cf}.ssk-grayscale>.ssk-reddit{background-color:#757575}.ssk-reddit:hover{background-color:#3a80c1}.ssk-reddit:hover{background-color:#3a80c1}.ssk-grayscale>.ssk-reddit:hover{background-color:#5f99cf}.ssk-reddit.ssk-icon{color:#5f99cf}.ssk-reddit.ssk-icon:hover{color:#3a80c1}.ssk-reddit2{background-color:#5f99cf}.ssk-grayscale>.ssk-reddit2{background-color:#757575}.ssk-reddit2:hover{background-color:#3a80c1}.ssk-reddit2:hover{background-color:#3a80c1}.ssk-grayscale>.ssk-reddit2:hover{background-color:#5f99cf}.ssk-reddit2.ssk-icon{color:#5f99cf}.ssk-reddit2.ssk-icon:hover{color:#3a80c1}.ssk-turquoise{background-color:#1abc9c}.ssk-turquoise:hover{background-color:#148f77}.ssk-emerald{background-color:#2ecc71}.ssk-emerald:hover{background-color:#25a25a}.ssk-peter-river{background-color:#3498db}.ssk-peter-river:hover{background-color:#217dbb}.ssk-belize-hole{background-color:#2980b9}.ssk-belize-hole:hover{background-color:#20638f}.ssk-amethyst{background-color:#9b59b6}.ssk-amethyst:hover{background-color:#804399}.ssk-wisteria{background-color:#8e44ad}.ssk-wisteria:hover{background-color:#703688}.ssk-wet-asphalt{background-color:#34495e}.ssk-wet-asphalt:hover{background-color:#222f3d}.ssk-midnight-blue{background-color:#2c3e50}.ssk-midnight-blue:hover{background-color:#1a242f}.ssk-green-sea{background-color:#16a085}.ssk-green-sea:hover{background-color:#107360}.ssk-nephritis{background-color:#27ae60}.ssk-nephritis:hover{background-color:#1e8449}.ssk-sunflower{background-color:#f1c40f}.ssk-sunflower:hover{background-color:#c29d0b}.ssk-orange{background-color:#f39c12}.ssk-orange:hover{background-color:#c87f0a}.ssk-carrot{background-color:#e67e22}.ssk-carrot:hover{background-color:#bf6516}.ssk-pumpkin{background-color:#d35400}.ssk-pumpkin:hover{background-color:#a04000}.ssk-alizarin{background-color:#e74c3c}.ssk-alizarin:hover{background-color:#d62c1a}.ssk-pomegranate{background-color:#c0392b}.ssk-pomegranate:hover{background-color:#962d22}.ssk-clouds{background-color:#cfd9db}.ssk-clouds:hover{background-color:#b1c2c6}.ssk-concrete{background-color:#95a5a6}.ssk-concrete:hover{background-color:#798d8f}.ssk-silver{background-color:#bdc3c7}.ssk-silver:hover{background-color:#a1aab0}.ssk-asbestos{background-color:#7f8c8d}.ssk-asbestos:hover{background-color:#667273}.ssk-dark-gray{background-color:#555}.ssk-dark-gray:hover{background-color:#3b3b3b}.ssk-black{background-color:#333}.ssk-black:hover{background-color:#1a1a1a}#article body,#instructions body,.md-preview body{color:#333;font-family:Roboto Condensed;font-size:14px;line-height:1.6;padding-top:10px;padding-bottom:10px;background-color:white;padding:30px}#article body>*:first-child,#instructions body>*:first-child,.md-preview body>*:first-child{margin-top:0!important}#article body>*:last-child,#instructions body>*:last-child,.md-preview body>*:last-child{margin-bottom:0!important}#article a,#instructions a,.md-preview a{text-decoration:none}#article a.absent,#instructions a.absent,.md-preview a.absent{color:#c00}#article h1,#instructions h1,.md-preview h1,#article h2,#instructions h2,.md-preview h2,#article h3,#instructions h3,.md-preview h3,#article h4,#instructions h4,.md-preview h4,#article h5,#instructions h5,.md-preview h5,#article h6,#instructions h6,.md-preview h6{margin:20px 0 10px;padding:0;font-weight:700;-webkit-font-smoothing:antialiased;cursor:text;position:relative}#article img,#instructions img,.md-preview img{max-width:100%}#article h1:hover a.anchor,#instructions h1:hover a.anchor,.md-preview h1:hover a.anchor,#article h2:hover a.anchor,#instructions h2:hover a.anchor,.md-preview h2:hover a.anchor,#article h3:hover a.anchor,#instructions h3:hover a.anchor,.md-preview h3:hover a.anchor,#article h4:hover a.anchor,#instructions h4:hover a.anchor,.md-preview h4:hover a.anchor,#article h5:hover a.anchor,#instructions h5:hover a.anchor,.md-preview h5:hover a.anchor,#article h6:hover a.anchor,#instructions h6:hover a.anchor,.md-preview h6:hover a.anchor{background:url(../../images/modules/styleguide/para.png) no-repeat 10px center;text-decoration:none}#article h1 tt,#instructions h1 tt,.md-preview h1 tt,#article h1 code,#instructions h1 code,.md-preview h1 code{font-size:inherit}#article h2 tt,#instructions h2 tt,.md-preview h2 tt,#article h2 code,#instructions h2 code,.md-preview h2 code{font-size:inherit}#article h3 tt,#instructions h3 tt,.md-preview h3 tt,#article h3 code,#instructions h3 code,.md-preview h3 code{font-size:inherit}#article h4 tt,#instructions h4 tt,.md-preview h4 tt,#article h4 code,#instructions h4 code,.md-preview h4 code{font-size:inherit}#article h5 tt,#instructions h5 tt,.md-preview h5 tt,#article h5 code,#instructions h5 code,.md-preview h5 code{font-size:inherit}#article h6 tt,#instructions h6 tt,.md-preview h6 tt,#article h6 code,#instructions h6 code,.md-preview h6 code{font-size:inherit}#article h1,#instructions h1,.md-preview h1{font-size:28px;color:black}#article h2,#instructions h2,.md-preview h2{font-size:24px;border-bottom:1px solid #ccc;color:black}#article h3,#instructions h3,.md-preview h3{font-size:18px}#article h4,#instructions h4,.md-preview h4{font-size:16px}#article h5,#instructions h5,.md-preview h5{font-size:14px}#article h6,#instructions h6,.md-preview h6{color:#777;font-size:14px}#article p,#instructions p,.md-preview p,#article blockquote,#instructions blockquote,.md-preview blockquote,#article ul,#instructions ul,.md-preview ul,#article ol,#instructions ol,.md-preview ol,#article dl,#instructions dl,.md-preview dl,#article table,#instructions table,.md-preview table,#article pre,#instructions pre,.md-preview pre{margin:15px 0}#article hr,#instructions hr,.md-preview hr{background:transparent url(../../images/modules/pulls/dirty-shade.png) repeat-x 0 0;border:0 none;color:#ccc;height:4px;padding:0}#article body>h2:first-child,#instructions body>h2:first-child,.md-preview body>h2:first-child{margin-top:0;padding-top:0}#article body>h1:first-child,#instructions body>h1:first-child,.md-preview body>h1:first-child{margin-top:0;padding-top:0}#article body>h1:first-child+h2,#instructions body>h1:first-child+h2,.md-preview body>h1:first-child+h2{margin-top:0;padding-top:0}#article body>h3:first-child,#instructions body>h3:first-child,.md-preview body>h3:first-child,#article body>h4:first-child,#instructions body>h4:first-child,.md-preview body>h4:first-child,#article body>h5:first-child,#instructions body>h5:first-child,.md-preview body>h5:first-child,#article body>h6:first-child,#instructions body>h6:first-child,.md-preview body>h6:first-child{margin-top:0;padding-top:0}#article a:first-child h1,#instructions a:first-child h1,.md-preview a:first-child h1,#article a:first-child h2,#instructions a:first-child h2,.md-preview a:first-child h2,#article a:first-child h3,#instructions a:first-child h3,.md-preview a:first-child h3,#article a:first-child h4,#instructions a:first-child h4,.md-preview a:first-child h4,#article a:first-child h5,#instructions a:first-child h5,.md-preview a:first-child h5,#article a:first-child h6,#instructions a:first-child h6,.md-preview a:first-child h6{margin-top:0;padding-top:0}#article h1 p,#instructions h1 p,.md-preview h1 p,#article h2 p,#instructions h2 p,.md-preview h2 p,#article h3 p,#instructions h3 p,.md-preview h3 p,#article h4 p,#instructions h4 p,.md-preview h4 p,#article h5 p,#instructions h5 p,.md-preview h5 p,#article h6 p,#instructions h6 p,.md-preview h6 p{margin-top:0}#article li p.first,#instructions li p.first,.md-preview li p.first{display:inline-block}#article ul,#instructions ul,.md-preview ul,#article ol,#instructions ol,.md-preview ol{padding-left:30px}#article ul :first-child,#instructions ul :first-child,.md-preview ul :first-child,#article ol :first-child,#instructions ol :first-child,.md-preview ol :first-child{margin-top:0}#article ul :last-child,#instructions ul :last-child,.md-preview ul :last-child,#article ol :last-child,#instructions ol :last-child,.md-preview ol :last-child{margin-bottom:0}#article dl,#instructions dl,.md-preview dl{padding:0}#article dl dt,#instructions dl dt,.md-preview dl dt{font-size:14px;font-weight:700;font-style:italic;padding:0;margin:15px 0 5px}#article dl dt:first-child,#instructions dl dt:first-child,.md-preview dl dt:first-child{padding:0}#article dl dt>:first-child,#instructions dl dt>:first-child,.md-preview dl dt>:first-child{margin-top:0}#article dl dt>:last-child,#instructions dl dt>:last-child,.md-preview dl dt>:last-child{margin-bottom:0}#article dl dd,#instructions dl dd,.md-preview dl dd{margin:0 0 15px;padding:0 15px}#article dl dd>:first-child,#instructions dl dd>:first-child,.md-preview dl dd>:first-child{margin-top:0}#article dl dd>:last-child,#instructions dl dd>:last-child,.md-preview dl dd>:last-child{margin-bottom:0}#article blockquote,#instructions blockquote,.md-preview blockquote{border-left:4px solid #ddd;padding:0 15px;color:#777}#article blockquote>:first-child,#instructions blockquote>:first-child,.md-preview blockquote>:first-child{margin-top:0}#article blockquote>:last-child,#instructions blockquote>:last-child,.md-preview blockquote>:last-child{margin-bottom:0}#article table,#instructions table,.md-preview table{padding:0}#article table tr,#instructions table tr,.md-preview table tr{border-top:1px solid #ccc;background-color:white;margin:0;padding:0}#article table tr:nth-child(2n),#instructions table tr:nth-child(2n),.md-preview table tr:nth-child(2n){background-color:#f8f8f8}#article table tr th,#instructions table tr th,.md-preview table tr th{font-weight:700;border:1px solid #ccc;text-align:left;margin:0;padding:6px 13px}#article table tr td,#instructions table tr td,.md-preview table tr td{border:1px solid #ccc;text-align:left;margin:0;padding:6px 13px}#article table tr th :first-child,#instructions table tr th :first-child,.md-preview table tr th :first-child,#article table tr td :first-child,#instructions table tr td :first-child,.md-preview table tr td :first-child{margin-top:0}#article table tr th :last-child,#instructions table tr th :last-child,.md-preview table tr th :last-child,#article table tr td :last-child,#instructions table tr td :last-child,.md-preview table tr td :last-child{margin-bottom:0}#article img,#instructions img,.md-preview img{max-width:100%}#article span.frame,#instructions span.frame,.md-preview span.frame{display:block;overflow:hidden}#article span.frame>span,#instructions span.frame>span,.md-preview span.frame>span{border:1px solid #ddd;display:block;float:left;overflow:hidden;margin:13px 0 0;padding:7px;width:auto}#article span.frame span img,#instructions span.frame span img,.md-preview span.frame span img{display:block;float:left}#article span.frame span span,#instructions span.frame span span,.md-preview span.frame span span{clear:both;color:#333;display:block;padding:5px 0 0}#article span.align-center,#instructions span.align-center,.md-preview span.align-center{display:block;overflow:hidden;clear:both}#article span.align-center>span,#instructions span.align-center>span,.md-preview span.align-center>span{display:block;overflow:hidden;margin:13px auto 0;text-align:center}#article span.align-center span img,#instructions span.align-center span img,.md-preview span.align-center span img{margin:0 auto;text-align:center}#article span.align-right,#instructions span.align-right,.md-preview span.align-right{display:block;overflow:hidden;clear:both}#article span.align-right>span,#instructions span.align-right>span,.md-preview span.align-right>span{display:block;overflow:hidden;margin:13px 0 0;text-align:right}#article span.align-right span img,#instructions span.align-right span img,.md-preview span.align-right span img{margin:0;text-align:right}#article span.float-left,#instructions span.float-left,.md-preview span.float-left{display:block;margin-right:13px;overflow:hidden;float:left}#article span.float-left span,#instructions span.float-left span,.md-preview span.float-left span{margin:13px 0 0}#article span.float-right,#instructions span.float-right,.md-preview span.float-right{display:block;margin-left:13px;overflow:hidden;float:right}#article span.float-right>span,#instructions span.float-right>span,.md-preview span.float-right>span{display:block;overflow:hidden;margin:13px auto 0;text-align:right}#article code,#instructions code,.md-preview code,#article tt,#instructions tt,.md-preview tt{margin:0 2px;padding:0 5px;white-space:nowrap;border:1px solid #eaeaea;background-color:#f8f8f8;border-radius:3px}#article pre code,#instructions pre code,.md-preview pre code{margin:0;padding:0;white-space:pre;border:none;background:transparent}#article .highlight pre,#instructions .highlight pre,.md-preview .highlight pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}#article pre,#instructions pre,.md-preview pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}#article pre code,#instructions pre code,.md-preview pre code,#article pre tt,#instructions pre tt,.md-preview pre tt{background-color:transparent;border:none}html{overflow-x:hidden}.bootbox-form textarea{height:300px}.placepicker-map{width:100%;height:300px}.topic .posts .content iframe,.topic .posts .content .img-responsive{max-width:85%;display:inline}.github-embed img.author-picture{float:left;width:16px;margin-right:.5em}.topic .posts h3{text-transform:uppercase;font-size:16px;font-weight:900}.github-embed h3{font-size:16px;margin:0;font-weight:700;color:#333}.mandatory{font-size:.8em;color:#999}.ir{float:right;padding-left:20px}@media print{a[href]:after{content:none!important}}.addressTag{background-image:url(/images/label.png);background-size:contain;background-repeat:no-repeat;width:400px;opacity:.7;margin-bottom:-24px;margin-top:-28px}.addressTag .address{opacity:1;color:#000;text-shadow:0 0 0 rgba(255,255,255,.3),1px 1px 0 rgba(255,255,255,.8);-webkit-transform:rotate(10.2deg);-khtml-transform:rotate(10.2deg);-moz-transform:rotate(10.2deg);transform:rotate(10.2deg);padding-left:44px;padding-top:50px;padding-bottom:20px;width:300px;height:200px;font-size:16px;font-weight:700}.orderTable th{white-space:nowrap}.orderTable .radio{padding-left:20px}.orderTable .table{margin-bottom:0}.orderTable img{max-width:100px}.orderTable .factone{margin-top:10px}.orderTable .btn-order{min-width:120px}.orderTable .fact{clear:both;float:left;margin-top:8px;margin-bottom:0}#tab-container{min-height:200px}.prices{width:100%;text-align:center}.prices ul{display:inline-block;padding-left:0;margin:0 auto;list-style-type:none}.prices li.cart{background:inherit;font-size:30px;padding:0;padding-top:10px;border:none;cursor:inherit}.prices li.cart:hover{color:#888;border:none;background:#fff}.prices li.cart p{font-size:13px;margin:0;margin-top:2px;margin-right:-5px;padding-bottom:2px;margin-bottom:-13px;clear:both}.prices .buy a:hover{text-decoration:none}.prices .buy a{color:#888}.prices li{cursor:pointer;color:#888;background:#eee;border-radius:4px;padding:10px;margin-top:5px;margin-left:6px;margin-right:6px;text-align:center;float:left;border:1px solid #fff}.prices li h4{color:#ee791d;margin-top:2px;margin-bottom:0}.prices li:hover{color:#000;background:#f4f4f4;border:1px solid #888}.prices li:hover h4{color:#ff4c08}.donate{width:20px;height:20px;margin-top:-4px;margin-left:4px;margin-right:6px;opacity:.5}.htMax200{width:200px}.htMax150{width:150px;overflow-x:hidden}.create .tab{width:110px}.pcb-dimensions{padding-left:0;padding-right:0;margin-right:-40px;line-height:32px;margin-left:-6px}.input-group .tag-editor{width:200px;background:#eee;box-shadow:0 0 9px rgba(0,153,176,.5);-webkit-box-shadow:0 0 9px rgba(0,153,176,.5);-moz-box-shadow:0 0 9px rgba(0,153,176,.5);border-top-right-radius:0;border-bottom-right-radius:0}.editProject{margin-right:15px}.selectOne{overflow-y:scroll;padding:0;height:400px}.selectOne i{display:none}.selectOne ul{width:100%;min-height:200px;list-style-type:none;margin:0;padding:10px;float:left;margin-right:10px}.selectOne li{margin:2px;padding:3px;font-size:14px;width:100%;cursor:hand;background:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.selectOne li:hover{background:#eee}@font-face{font-family:Roboto Condensed;src:url(/fonts/RobotoCondensed-Regular-webfont.eot);src:url(/fonts/RobotoCondensed-Regular-webfont.eot?#iefix) format('embedded-opentype'),url(/fonts/RobotoCondensed-Regular-webfont.woff) format('woff'),url(/fonts/RobotoCondensed-Regular-webfont.ttf) format('truetype'),url(/fonts/RobotoCondensed-Regular-webfont.svg#roboto_condensedregular) format('svg')}@font-face{font-family:Menu;src:url(/fonts/OCRAExtended.eot);src:url(/fonts/OCRAExtended.eot?#iefix) format('embedded-opentype'),url(/fonts/OCRAExtended.woff) format('woff'),url(/fonts/OCRAExtended.ttf) format('truetype'),url(/fonts/OCRAExtended.svg#OCRAExtended) format('svg')}iframe.codebender-plugin{border:0;height:510px;width:100%;margin:10px 0}@media only screen and (max-width:321px){iframe.codebender-plugin{border:0;height:180px;width:100%}}@media only screen and (max-width:320px){iframe.codebender-plugin{border:0;height:180px;width:100%}}@media only screen and (min-device-width:768px) and (max-device-width:1000px) and (orientation:landscape){iframe.codebender-plugin{border:0;height:360px;width:100%}}@media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:portrait){iframe.codebender-plugin{border:0;height:360px;width:100%}}.fotorama{margin-bottom:30px}.align-right{text-align:right}.align-center{text-align:center}.etabs{margin:0;padding-left:10px}.creator{white-space:nowrap}.tab{width:140px;display:inline-block;zoom:1;display:inline;background:#fff;border-bottom:none}.tab a{color:#888;text-decoration:none;text-align:center;font-size:16px;line-height:24px;display:block;padding:7px;outline:none}.tab a:hover{color:#000}.tab.active{border-top:solid 1px #888;border-left:solid 1px #888;border-right:solid 1px #888;color:#000;padding-top:1px;position:relative;top:1px;border-color:#888;border-top-left-radius:2px;border-top-right-radius:2px}.tab a.active{color:#000}.tab-container .panel-container{border-top:solid #888 1px;padding:20px}#spinner{margin:50px}.view-project .title{font-family:Roboto Condensed;font-weight:700;font-size:34px;padding-top:16px;margin-bottom:-6px;white-space:nowrap;text-overflow:ellipsis}.view-project .well{background:#fff}#donateForm{display:none}.view-project .actions{border:1px solid #eee;padding:0;border-radius:3px;width:100%;float:left}.view-project .actions-wrapper{padding-left:15px;padding-right:15px;padding-bottom:15px;margin-top:-25px;width:100%}.view-project .actionRow:hover{color:#000}.view-project .actionRowFirst{float:left;color:#888;width:100%;padding:8px;border-bottom:1px solid #eee}.view-project .actionRow{float:left;cursor:pointer;color:#888;width:100%;padding:8px;border-bottom:1px solid #eee}.view-project .actionRowShare{padding-top:7px;padding-bottom:5px;padding-right:0}.view-project .last{border-bottom:0}.view-project .actionRow .action{width:30px;padding-left:5px}.view-project .overview .left{float:left;padding-right:10px;text-align:right;width:80px}.view-project .overview .right{padding-right:5px;padding-left:5px;clear:right}.view-project .overview{overflow:hidden;font-size:14px;padding-left:16px}.profile .wip,.view-project .wip{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1;border-radius:3px;width:100%;text-align:center;padding-top:10px;padding-bottom:10px;margin-bottom:10px}.view-project .actionRow .count{float:right;text-align:right;padding-right:10px}.view-project .avatar{float:left}.goto,.like,.collect,.view{cursor:pointer}.like:hover{color:pink}.like i.active{color:red}.collect:hover{color:lightgreen}.collect i.active{color:green}.view:hover{color:lightblue}.view i.active{color:blue}.tag-editor{border:1px solid #ccc;border-radius:4px;height:36px}.tag-editor li{line-height:28px}.clip-corner{pointer-events:none;overflow:hidden;display:block;position:absolute;top:6px;height:200px;width:200px}.corner-ribbon{width:238px;text-align:center;line-height:31px;letter-spacing:1px;transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}.corner-ribbon.corner-sticky{position:absolute}.corner-ribbon.shadow{box-shadow:0 0 3px rgba(0,0,0,.3)}.corner-ribbon.top-left{top:50px;left:-46px;transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}.corner-ribbon.normal{background:rgba(0,153,176,.5);color:#fff}.corner-ribbon.black{background:#333}.corner-ribbon.grey{background:#999}.corner-ribbon.blue{background:#39d}.corner-ribbon.green{background:#2c7}.corner-ribbon.turquoise{background:#1b9}.corner-ribbon.purple{background:#95b}.corner-ribbon.red{background:#e43}.corner-ribbon.orange{background:#e82}.corner-ribbon.yellow{background:#ec0}.input-group .form-control{z-index:inherit}.filelists{display:table;width:100%}.filelist .del-file{vertical-align:middle;margin-right:2px;margin-top:3px;cursor:pointer}.filelist .list-image .del-file{margin-top:18px}.filelist-row{display:table-row}.filelist{display:table-cell;width:50%;vertical-align:top}.filelist-button{width:60px}.filelist-image-text{height:50px;line-height:50px;position:relative}.filelist-image{vertical-align:middle;position:absolute;top:0;right:20px;height:50px}.filelist-publish{display:table-cell;width:200px;padding:10px;text-align:center;vertical-align:top}.connected{border:2px dashed #ccc;width:100%;min-height:200px;list-style-type:none;margin:0;padding:10px;float:left;margin-right:10px}.connected li{margin:0;padding:3px;font-size:14px;width:100%;cursor:move;background:#fff;overflow:hidden;text-overflow:ellipsis}.clear{clear:both}.center-ad{text-align:center;padding-top:10px;padding-bottom:10px}.panel-container hr{margin-top:-8px;margin-bottom:10px}.panel-container .small{font-size:93%}.news hr{margin-top:10px;margin-bottom:10px}.news h4{margin-top:0}.dropHeader{font-size:19px}.github-fixed-branch{width:150px!important}.github-fixed-branch select[disabled]{opacity:0;hand:normal}.bootstrap-tagsinput{display:block;width:auto;margin:auto 0;height:35px}span[class^=ion-]{padding-right:6px}.menu-avatar-wrapper{margin-top:-4px;margin-left:-6px;border:2px solid rgba(60,99,174,.54);width:36px;height:36px;border-radius:22px;background:#fff}.menu-avatar-wrapper img{height:26px;position:relative;top:3px;vertical-align:top;left:3px;width:26px;border-radius:24px}.menu-avatar-wrapper i{margin-left:10px}.user-avatar-wrapper{float:left;width:66px;height:66px;border:3px solid #3c63ae;border-radius:100px;background:#fff}.user-avatar-wrapper img{height:60px;width:60px;border-radius:100px}.avatar-wrapper{position:absolute;left:10px;top:15px;border:2px solid #3c63ae;border-radius:36px;background:#fff}.avatar-container{float:left;padding-right:20px}.avatar-wrapper img{height:36px;width:36px;border-radius:36px}.form-avatar-wrapper{border-radius:60px;float:left;margin:10px;margin-top:20px;border:2px solid #3c63ae;background:#fff}.form-avatar-wrapper img{width:60px;height:60px;border-radius:60px}footer{position:absolute;bottom:0;width:100%;height:45px;line-height:45px}.embedHeader{background-color:#e4e4e4;width:100%;padding:5px;border-radius:4px 4px 0 0;border:1px solid #ccc;position:relative;white-space:nowrap;margin-bottom:-19px}.embedHeader img{float:right;height:44px;border-radius:3px}.embedHeader .embedFile{display:block;max-width:90%;overflow:hidden;text-overflow:ellipsis}pre{max-height:350px}.alert{margin-top:20px}.tn{position:relative;text-align:center;display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail{padding:0;border-radius:0;box-shadow:0 0 5px #ccc,inset 0 0 0 #000}body{font-family:Roboto Condensed,Helvetica,Arial,sans-serif;position:relative}.search-pad{margin:4px}.search-pad .input-group>.form-control{width:100%;border-radius:29px 0 0 29px;box-shadow:inherit;background:rgba(234,233,233,.56)}.search-pad .form-control:hover,.search-pad .form-control:focus,.search-pad .add-on:hover{background:#eee}.search-pad .form-control{color:inherit;border:0}.search-pad .input-group-addon{width:auto;border:0;color:inherit;border-radius:0 29px 29px 0;background:rgba(234,233,233,.56)}.promo{margin-left:10px;margin-right:10px}.promo-text{font-weight:300;font-size:30px;color:#333;white-space:nowrap}.promo-headline{font-weight:300;height:40px;padding-right:10px;padding-left:10px;font-size:30px;line-height:37px;color:#fff;border-radius:4px;white-space:nowrap}.flash{box-shadow:3px 2px 15px #888;margin-top:20px}.fixed{position:fixed;z-index:1;top:0;left:0;width:100%}.navbar{margin-bottom:0}.sticky{width:100%;background:rgba(0,153,176,.5);box-shadow:0 6px 15px rgba(59,104,111,.71);-webkit-box-shadow:0 6px 15px rgba(59,104,111,.71);-moz-box-shadow:0 6px 15px rgba(59,104,111,.71);border:1px rgba(0,153,176,.5);border-radius:0;min-height:inherit}.sticky .input-group-addon{font-size:14px}.sticky .tag-editor li{font-size:14px;line-height:20px}.sticky .tag-editor{height:28px}.sticky .tag-editor .placeholder{padding:0}.sticky .tag-editor .tag-editor-tag{padding-left:0}.sticky ul li,.sticky ul li>a,.navbar-default .navbar-nav>li>a{color:#3c63ae;padding-right:4px;font-size:14px;float:left}.sticky .navbar-nav>li>a{padding:0 9px;line-height:24px;border-radius:29px;margin-bottom:6px;margin-top:6px;background:rgba(234,233,233,.56)}.sticky .navbar-nav>li>a.active,.sticky .navbar-nav>li>a:hover,.sticky .navbar-nav>li>a:focus{background:#eee;box-shadow:0 0 9px rgba(0,153,176,.5);-webkit-box-shadow:0 0 9px rgba(0,153,176,.5);-moz-box-shadow:0 0 9px rgba(0,153,176,.5)}.input-group .bootstrap-select{z-index:inherit!important}.navbar-nav .open .dropdown-menu{position:absolute}.error{color:red}.dropper-dropzone{border:2px dashed #ccc}.well-sm{padding-left:16px;padding-right:16px}.horizontal label{font-size:16px;font-weight:400}.below{padding-bottom:10px}.profile hr{margin-top:10px;margin-bottom:10px;border:0;border-top:1px solid #ccc}hr{margin-top:13px;margin-bottom:2px;border:0;border-top:1px solid #ccc}h4,.h4{font-size:20px}.navbar-toggle{padding:inherit;line-height:44px;color:#888}.navbar-simple .brand{color:#000;padding-top:15px;padding-bottom:15px}.navbar-simple .brand a{color:#000}.navbar-simple .navbar-inner .nav li a{white-space:nowrap}.navbar-simple .navbar-inner .nav{float:right}.navbar-simple .navbar-inner .nav li a{background:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;color:#888}.navbar-simple .navbar-inner .nav li a:hover{background:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;color:#000}.page{margin-top:12px}.box-move:before,.box-move:after{background:initial!important;box-shadow:initial!important;-moz-box-shadow:initial!important;-webkit-box-shadow:initial!important}.floaters{margin-top:24px;text-align:center}.box .featured{color:yellow;opacity:.75;font-size:50px;position:absolute;top:22px;width:24px;right:33px}.box .forSale{color:#80ccd8;opacity:.75;font-size:50px;position:absolute;top:188px;width:24px;right:33px}.box .updated{pointer-events:none;position:absolute;font-size:12px;display:inline-block;top:10px;right:10px;width:200px;height:19px;text-align:right;overflow:hidden}.box .creator{pointer-events:none;position:absolute;font-size:12px;display:inline-block;top:10px;left:58px;width:200px;height:25px;text-align:left;overflow:hidden}.box .shade{pointer-events:none;position:absolute;top:6px;left:6px;background:linear-gradient(to bottom,rgba(0,0,0,.5) 0,transparent 100%);height:90px;width:300px}.profile-picture{position:absolute;top:10px;left:10px;display:inline-block;width:50px;height:50px;background:#fff;border:2px solid #3c63ae;opacity:.9;border-radius:25px;float:left;cursor:pointer;-webkit-transition:border-color .1s ease-in-out;-moz-transition:border-color .1s ease-in-out;-o-transition:border-color .1s ease-in-out;transition:border-color .1s ease-in-out}.profile-picture img{width:46px;height:46px;border-radius:25px}.box .hardware{width:100%;overflow:hidden;display:block;min-height:272px;min-width:292px;background:#fff;background-position:center;background-repeat:no-repeat;background-size:cover;border:1px solid #bababa}.box .hardware img{display:block;margin-left:auto;margin-right:auto;outline:0;max-width:100%;height:auto}.box .profile-name{width:200px;height:14px;bottom:94px;text-align:right;right:20px;position:absolute;white-space:nowrap;text-overflow:ellipsis;display:inline-block;overflow:hidden;color:#ddd;text-shadow:1px 1px #0099b0;cursor:pointer;font-size:12px}.box .buttons:hover{opacity:1.0;transition:opacity .25s ease-in-out;-moz-transition:opacity .25s ease-in-out;-webkit-transition:opacity .25s ease-in-out}.box .buttons{opacity:.3;transition:opacity .25s ease-in-out;-moz-transition:opacity .25s ease-in-out;-webkit-transition:opacity .25s ease-in-out;bottom:57px;margin:0 1px;font-size:20px;padding:8px;position:absolute;overflow:hidden;text-shadow:1px 1px #333;color:#fff;width:300px;background-color:rgba(166,116,178,.7)}.box .button{width:33%;float:left;text-align:center}.box .button:first-child{text-align:left}.box .button:last-child{text-align:right}.box a:hover{text-decoration:none;color:rgba(0,0,0,.8)}.box a{color:rgba(0,0,0,.8)}.box .title{padding:10px 0;height:52px;font-weight:700;font-family:Menu;line-height:19px;display:block;display:-webkit-box;margin:0 auto;text-align:center;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;color:rgba(0,0,0,.8);text-shadow:0 1px 0 #fff}.box{color:#fff;text-shadow:0 1px 0 #000;position:relative;display:inline-block;background:#e6e2d6;-moz-border-radius:4px;border-radius:4px;padding:5px;line-height:1;margin-right:10px;margin-left:10px;margin-bottom:25px;width:312px;vertical-align:top}.box:before,.box:after{z-index:-1;position:absolute;content:"";bottom:12px;left:10px;width:50%;top:80%;max-width:300px;background:rgba(0,0,0,.7);-webkit-box-shadow:0 15px 10px rgba(0,0,0,.7);-moz-box-shadow:0 15px 10px rgba(0,0,0,.7);box-shadow:0 15px 10px rgba(0,0,0,.7);-webkit-transform:rotate(-3deg);-moz-transform:rotate(-3deg);-o-transform:rotate(-3deg);-ms-transform:rotate(-3deg);transform:rotate(-3deg)}.box:after{-webkit-transform:rotate(3deg);-moz-transform:rotate(3deg);-o-transform:rotate(3deg);-ms-transform:rotate(3deg);transform:rotate(3deg);right:10px;left:auto}.footer{clear:both;text-align:center;padding-top:20px;padding-bottom:20px}.navbar-right{margin-right:inherit}.sticky .navbar{min-height:inherit}.menu-text{padding-top:15px}.md-editor>textarea{background:#fff;padding:10px}.md-editor>.md-preview{padding:10px}.ocr{display:inline-block;font-family:Menu!important;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.navbar-brand{background:url(/images/logo.png) no-repeat;background-size:44px 44px;background-position:6px 12px;height:68px;margin-left:-5px;line-height:28px;padding-left:60px;font-size:30px;color:#888}.navbar-brand:hover{color:#888}.navbar-nav>li>a{font-size:18px;line-height:32px}.bootstrap-select>.dropdown-toggle{z-index:inherit}.modal-backdrop{z-index:1035}.modal{z-index:999991}.md-nooverflow{position:inherit}.fotorama__html div,.fotorama__html iframe{width:100%;height:100%}.navbar-fixed-bottom{padding-left:10px;right:0;left:initial;text-align:center;border-left:1px solid #e7e7e7;border-radius:4px}.navbar-fixed-bottom button{display:none;margin-right:10px}.well{box-shadow:3px 2px 15px #888}.form-signin{max-width:330px;padding:15px;margin:0 auto}.form-signin .form-signin-heading,.form-signin .checkbox{margin-bottom:10px}.form-signin .checkbox{font-weight:400}.form-signin .form-control{position:relative;font-size:16px;height:auto;padding:10px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.form-signin .form-control:focus{z-index:2}.form-signin input[type=text]{margin-bottom:-1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.form-signin input[type=password]{margin-bottom:10px;border-top-left-radius:0;border-top-right-radius:0}div.toc{counter-reset:chapter}div.toc>ol{padding-left:0}div.toc>ol>ol{padding-left:30px}div.toc>ol>ol>ol{padding-left:30px}div.toc>ol>li{list-style-type:none;counter-increment:chapter;counter-reset:section;padding-top:25px;font-size:20px;padding-bottom:10px}div.toc>ol>ol>li{list-style-type:none;counter-increment:section;counter-reset:none;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;padding-top:10px;padding-bottom:5px}div.toc>ol>ol>ol>li{list-style-type:none;counter-increment:subsection;counter-reset:none;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;padding-top:10px;padding-bottom:5px}div.toc>ol li:before{content:"SECTION " counter(chapter) ": ";display:block;float:left;width:6em}div.toc>ol ol li:before{font-weight:700;content:counter(chapter) "." counter(section) ".";width:2em}div.toc>ol ol ol li:before{font-weight:700;content:counter(chapter) "." counter(section) "." counter(subsection) ".";width:3em}.affiliate{font:13px Helvetica,arial,freesans,clean,sans-serif;background-color:#fff;border:1px solid #aaa;border-radius:4px;position:relative;min-height:102px;box-shadow:5px 5px 5px #aaa;margin-top:10px}.affiliate a{color:#333;text-decoration:none}.affiliate div.price{color:white;border-radius:2px;font-size:13px;padding:3px 4px;margin-right:12px}.affiliate div.stock{font-weight:400;color:#777;padding-top:5px}.affiliate h3{padding:10px;font-size:16px;margin:0;font-weight:700;color:#333}.affiliate h3 div.ellipsis{max-height:51px;overflow:hidden}.affiliate .image{float:left;padding-bottom:8px;padding-right:17px}.affiliate .image img{float:left;height:100px;margin-right:.5em}@media(max-width:768px){.navbar-nav>li>a{padding-top:12px;padding-bottom:12px}.view-project .actionRowFirst,.view-project .actionRow,.view-project .actions{border:0}.page{margin-top:0}.view-project .title{padding-top:0}.navbar{min-height:50px}.navbar-brand{background-size:22px 22px;background-position:4px 14px}.tab{width:60px}.smalltabs .tab{width:40px}.view-project .title{font-size:28px}} \ No newline at end of file diff --git a/lib/MySensors/Logparser/logparser.html b/lib/MySensors/Logparser/logparser.html deleted file mode 100644 index 3596ae67..00000000 --- a/lib/MySensors/Logparser/logparser.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - Log Parser | MySensors - Create your own Connected Home Experience - - - - - -
-

Paste log from gateway or node here:

- - - - -

Human readable output:

-
- - - - - - - - - - - - - -
Node IdChild SensorCommand TypeEcho Req/RespTypePayloadDescription
-
-
- - - - - diff --git a/lib/MySensors/Logparser/logparser.js b/lib/MySensors/Logparser/logparser.js deleted file mode 100644 index efc2e9f0..00000000 --- a/lib/MySensors/Logparser/logparser.js +++ /dev/null @@ -1,579 +0,0 @@ -function copyTextToClipboard(text) { - var textArea = document.createElement("textarea"); - - // - // *** This styling is an extra step which is likely not required. *** - // - // Why is it here? To ensure: - // 1. the element is able to have focus and selection. - // 2. if element was to flash render it has minimal visual impact. - // 3. less flakyness with selection and copying which **might** occur if - // the textarea element is not visible. - // - // The likelihood is the element won't even render, not even a flash, - // so some of these are just precautions. However in IE the element - // is visible whilst the popup box asking the user for permission for - // the web page to copy to the clipboard. - // - - // Place in top-left corner of screen regardless of scroll position. - textArea.style.position = 'fixed'; - textArea.style.top = 0; - textArea.style.left = 0; - - // Ensure it has a small width and height. Setting to 1px / 1em - // doesn't work as this gives a negative w/h on some browsers. - textArea.style.width = '2em'; - textArea.style.height = '2em'; - - // We don't need padding, reducing the size if it does flash render. - textArea.style.padding = 0; - - // Clean up any borders. - textArea.style.border = 'none'; - textArea.style.outline = 'none'; - textArea.style.boxShadow = 'none'; - - // Avoid flash of white box if rendered for any reason. - textArea.style.background = 'transparent'; - - - textArea.value = text; - - document.body.appendChild(textArea); - - textArea.select(); - - try { - var successful = document.execCommand('copy'); - var msg = successful ? 'successful' : 'unsuccessful'; - console.log('Copying text command was ' + msg); - } catch (err) { - console.log('Oops, unable to copy'); - } - - document.body.removeChild(textArea); -} - -var types = { -"presentation":[ -"S_DOOR", -"S_MOTION", -"S_SMOKE", -"S_BINARY", -"S_DIMMER", -"S_COVER", -"S_TEMP", -"S_HUM", -"S_BARO", -"S_WIND", -"S_RAIN", -"S_UV", -"S_WEIGHT", -"S_POWER", -"S_HEATER", -"S_DISTANCE", -"S_LIGHT_LEVEL", -"S_ARDUINO_NODE", -"S_ARDUINO_REPEATER_NODE", -"S_LOCK", -"S_IR", -"S_WATER", -"S_AIR_QUALITY", -"S_CUSTOM", -"S_DUST", -"S_SCENE_CONTROLLER", -"S_RGB_LIGHT", -"S_RGBW_LIGHT", -"S_COLOR_SENSOR", -"S_HVAC", -"S_MULTIMETER", -"S_SPRINKLER", -"S_WATER_LEAK", -"S_SOUND", -"S_VIBRATION", -"S_MOISTURE", -"S_INFO", -"S_GAS", -"S_GPS", -"S_WATER_QUALITY" -], -"internal": [ -"I_BATTERY_LEVEL", -"I_TIME", -"I_VERSION", -"I_ID_REQUEST", -"I_ID_RESPONSE", -"I_INCLUSION_MODE", -"I_CONFIG", -"I_FIND_PARENT_REQUEST", -"I_FIND_PARENT_RESPONSE", -"I_LOG_MESSAGE", -"I_CHILDREN", -"I_SKETCH_NAME", -"I_SKETCH_VERSION", -"I_REBOOT", -"I_GATEWAY_READY", -"I_SIGNING_PRESENTATION", -"I_NONCE_REQUEST", -"I_NONCE_RESPONSE", -"I_HEARTBEAT_REQUEST", -"I_PRESENTATION", -"I_DISCOVER_REQUEST", -"I_DISCOVER_RESPONSE", -"I_HEARTBEAT_RESPONSE", -"I_LOCKED", -"I_PING", -"I_PONG", -"I_REGISTRATION_REQUEST", -"I_REGISTRATION_RESPONSE", -"I_DEBUG", -"I_SIGNAL_REPORT_REQUEST", -"I_SIGNAL_REPORT_REVERSE", -"I_SIGNAL_REPORT_RESPONSE", -"I_PRE_SLEEP_NOTIFICATION", -"I_POST_SLEEP_NOTIFICATION" -], -"subtype":[ -"V_TEMP", -"V_HUM", -"V_STATUS", -"V_PERCENTAGE", -"V_PRESSURE", -"V_FORECAST", -"V_RAIN", -"V_RAINRATE", -"V_WIND", -"V_GUST", -"V_DIRECTION", -"V_UV", -"V_WEIGHT", -"V_DISTANCE", -"V_IMPEDANCE", -"V_ARMED", -"V_TRIPPED", -"V_WATT", -"V_KWH", -"V_SCENE_ON", -"V_SCENE_OFF", -"V_HVAC_FLOW_STATE", -"V_HVAC_SPEED", -"V_LIGHT_LEVEL", -"V_VAR1", -"V_VAR2", -"V_VAR3", -"V_VAR4", -"V_VAR5", -"V_UP", -"V_DOWN", -"V_STOP", -"V_IR_SEND", -"V_IR_RECEIVE", -"V_FLOW", -"V_VOLUME", -"V_LOCK_STATUS", -"V_LEVEL", -"V_VOLTAGE", -"V_CURRENT", -"V_RGB", -"V_RGBW", -"V_ID", -"V_UNIT_PREFIX", -"V_HVAC_SETPOINT_COOL", -"V_HVAC_SETPOINT_HEAT", -"V_HVAC_FLOW_MODE", -"V_TEXT", -"V_CUSTOM", -"V_POSITION", -"V_IR_RECORD", -"V_PH", -"V_ORP", -"V_EC", -"V_VAR", -"V_VA", -"V_POWER_FACTOR" -], -"stream":[ -"ST_FIRMWARE_CONFIG_REQUEST", -"ST_FIRMWARE_CONFIG_RESPONSE", -"ST_FIRMWARE_REQUEST", -"ST_FIRMWARE_RESPONSE", -"ST_SOUND", -"ST_IMAGE"], - command: [ -"PRESENTATION", -"SET", -"REQ", -"INTERNAL", -"STREAM" - ], -"payloadtype":[ -"P_STRING", -"P_BYTE", -"P_INT16", -"P_UINT16", -"P_LONG32", -"P_ULONG32", -"P_CUSTOM", -"P_FLOAT32" -]}; - -//mysgw: Client 0: 0;0;3;0;18;PING -var rprefix = "(?:\\d+ )?(?:mysgw: )?(?:Client 0: )?"; -var match = [ - { re: "MCO:BGN:INIT CP=([^,]+)", d: "Core initialization with capabilities $1" }, - { re: "MCO:BGN:INIT (\\w+),CP=([^,]+),VER=(.*)", d: "Core initialization of $1, with capabilities $2, library version $3" }, - { re: "MCO:BGN:INIT (\\w+),CP=([^,]+),REL=(.*),VER=(.*)", d: "Core initialization of $1, with capabilities $2, library version $4, release $3" }, - { re: "MCO:BGN:INIT (\\w+),CP=([^,]+),FQ=(\\d+),REL=(.*),VER=(.*)", d: "Core initialization of $1, with capabilities $2, CPU frequency $4 MHz, library version $5, release $4" }, - { re: "MCO:BGN:BFR", d: "Callback before()" }, - { re: "MCO:BGN:STP", d: "Callback setup()" }, - { re: "MCO:BGN:INIT OK,TSP=(.*)", d: "Core initialized, transport status $1, (1=initialized, 0=not initialized, NA=not available)" }, - { re: "MCO:BGN:NODE UNLOCKED", d: "Node successfully unlocked (see signing chapter)" }, - { re: "!MCO:BGN:TSP FAIL", d: "Transport initialization failed" }, - { re: "MCO:REG:REQ", d: "Registration request" }, - { re: "MCO:REG:NOT NEEDED", d: "No registration needed (i.e. GW)" }, - { re: "!MCO:SND:NODE NOT REG", d: "Node is not registered, cannot send message" }, - { re: "MCO:PIM:NODE REG=(\\d+)", d: "Registration response received, registration status $1" }, - { re: "MCO:PIM:ROUTE N=(\\d+),R=(\\d+)", d: "Routing table, messages to node $1 are routed via node $2" }, - { re: "MCO:SLP:MS=(\\d+),SMS=(\\d+),I1=(\\d+),M1=(\\d+),I2=(\\d+),M2=(\\d+)", d: "Sleep node, duration $1 ms, SmartSleep=$2, Int1=$3, Mode1=$4, Int2=$5, Mode2=$6" }, - { re: "MCO:SLP:MS=(\\d+)", d: "Sleep node, duration $1 ms" }, - { re: "MCO:SLP:TPD", d: "Sleep node, powerdown transport" }, - { re: "MCO:SLP:WUP=(-?\\d+)", d: "Node woke-up, reason/IRQ=$1 (-2=not possible, -1=timer, >=0 IRQ)" }, - { re: "!MCO:SLP:FWUPD", d: "Sleeping not possible, FW update ongoing" }, - { re: "!MCO:SLP:REP", d: "Sleeping not possible, repeater feature enabled" }, - { re: "!MCO:SLP:TNR", d: " Transport not ready, attempt to reconnect until timeout" }, - { re: "MCO:NLK:NODE LOCKED. UNLOCK: GND PIN (\\d+) AND RESET", d: "Node locked during booting, see signing documentation for additional information" }, - { re: "MCO:NLK:TPD", d: "Powerdown transport" }, - { re: "TSM:INIT", d: "Transition to Init state" }, - { re: "TSM:INIT:STATID=(\\d+)", d: "Init static node id $1" }, - { re: "TSM:INIT:TSP OK", d: "Transport device configured and fully operational" }, - { re: "TSM:INIT:GW MODE", d: "Node is set up as GW, thus omitting ID and findParent states" }, - { re: "!TSM:INIT:TSP FAIL", d: "Transport device initialization failed" }, - { re: "TSM:FPAR", d: "Transition to Find Parent state" }, - { re: "TSM:FPAR:STATP=(\\d+)", d: "Static parent $1 has been set, skip finding parent" }, - { re: "TSM:FPAR:OK", d: "Parent node identified" }, - { re: "!TSM:FPAR:NO REPLY", d: "No potential parents replied to find parent request" }, - { re: "!TSM:FPAR:FAIL", d: "Finding parent failed" }, - { re: "TSM:ID", d: "Transition to Request Id state" }, - { re: "TSM:ID:OK,ID=(\\d+)", d: "Node id $1 is valid" }, - { re: "TSM:ID:REQ", d: "Request node id from controller" }, - { re: "!TSM:ID:FAIL", d: "Did not receive a node id from controller. Is your controller connected and correctly configured?" }, - { re: "!TSM:ID:FAIL,ID=(\\d+)", d: "Id verification failed, $1 is invalid" }, - { re: "TSM:UPL", d: "Transition to Check Uplink state" }, - { re: "TSM:UPL:OK", d: "Uplink OK, GW returned ping" }, - { re: "!TSM:UPL:FAIL", d: "Uplink check failed, i.e. GW could not be pinged" }, - { re: "TSM:READY:NWD REQ", d: "Send transport network discovery request" }, - { re: "TSM:READY:SRT", d: "Save routing table" }, - { re: "TSM:READY:ID=(\\d+),PAR=(\\d+),DIS=(\\d+)", d: "Transport ready, node id $1, parent node id $2, distance to GW is $3" }, - { re: "!TSM:READY:UPL FAIL,SNP", d: "Too many failed uplink transmissions, search new parent" }, - { re: "!TSM:READY:FAIL,STATP", d: "Too many failed uplink transmissions, static parent enforced" }, - { re: "TSM:READY", d: "Transition to Ready state" }, - { re: "TSM:FAIL:DIS", d: "Disable transport" }, - { re: "TSM:FAIL:CNT=(\\d+)", d: "Transition to Failure state, consecutive failure counter is $1" }, - { re: "TSM:FAIL:PDT", d: "Power-down transport" }, - { re: "TSM:FAIL:RE-INIT", d: "Attempt to re-initialize transport" }, - { re: "TSF:CKU:OK,FCTRL", d: "Uplink OK, flood control prevents pinging GW in too short intervals" }, - { re: "TSF:CKU:OK", d: "Uplink OK" }, - { re: "TSF:CKU:DGWC,O=(\\d+),N=(\\d+)", d: "Uplink check revealed changed network topology, old distance $1, new distance $2" }, - { re: "TSF:CKU:FAIL", d: "No reply received when checking uplink" }, - { re: "TSF:SID:OK,ID=(\\d+)", d: "Node id $1 assigned" }, - { re: "!TSF:SID:FAIL,ID=(\\d+)", d: "Assigned id $1 is invalid" }, - { re: "TSF:PNG:SEND,TO=(\\d+)", d: "Send ping to destination $1" }, - { re: "!TSF:PNG:ACTIVE", d: "Ping active, cannot start new ping" }, - { re: "TSF:WUR:MS=(\\d+)", d: "Wait until transport ready, timeout $1" }, - { re: "TSF:MSG:ECHO REQ", d: "ECHO message requested" }, - { re: "TSF:MSG:ECHO", d: "ECHO message, do not proceed but forward to callback" }, - { re: "TSF:MSG:FPAR RES,ID=(\\d+),D=(\\d+)", d: "Response to find parent request received from node $1 with distance $2 to GW" }, - { re: "TSF:MSG:FPAR PREF FOUND", d: "Preferred parent found, i.e. parent defined via MY_PARENT_NODE_ID" }, - { re: "TSF:MSG:FPAR OK,ID=(\\d+),D=(\\d+)", d: "Find parent response from node $1 is valid, distance $2 to GW" }, - { re: "!TSF:MSG:FPAR INACTIVE", d: "Find parent response received, but no find parent request active, skip response" }, - { re: "TSF:MSG:FPAR REQ,ID=(\\d+)", d: "Find parent request from node $1" }, - { re: "TSF:MSG:PINGED,ID=(\\d+),HP=(\\d+)", d: "Node pinged by node $1 with $2 hops" }, - { re: "TSF:MSG:PONG RECV,HP=(\\d+)", d: "Pinged node replied with $1 hops" }, - { re: "!TSF:MSG:PONG RECV,INACTIVE", d: "Pong received, but !pingActive" }, - { re: "TSF:MSG:BC", d: "Broadcast message received" }, - { re: "TSF:MSG:GWL OK", d: "Link to GW ok" }, - { re: "TSF:MSG:FWD BC MSG", d: "Controlled broadcast message forwarding" }, - { re: "TSF:MSG:REL MSG", d: "Relay message" }, - { re: "TSF:MSG:REL PxNG,HP=(\\d+)", d: "Relay PING/PONG message, increment hop counter to $1" }, - { re: "!TSF:MSG:LEN,(\\d+)!=(\\d+)", d: "Invalid message length, $1 (actual) != $2 (expected)" }, - { re: "!TSF:MSG:PVER,(\\d+)!=(\\d+)", d: "Message protocol version mismatch, $1 (actual) != $2 (expected)" }, - { re: "!TSF:MSG:SIGN VERIFY FAIL", d: "Signing verification failed" }, - { re: "!TSF:MSG:REL MSG,NORP", d: "Node received a message for relaying, but node is not a repeater, message skipped" }, - { re: "!TSF:MSG:SIGN FAIL", d: "Signing message failed" }, - { re: "!TSF:MSG:GWL FAIL", d: "GW uplink failed" }, - { re: "!TSF:MSG:ID TK INVALID", d: "Token for ID request invalid" }, - { re: "TSF:SAN:OK", d: "Sanity check passed" }, - { re: "!TSF:SAN:FAIL", d: "Sanity check failed, attempt to re-initialize radio" }, - { re: "TSF:CRT:OK", d: "Clearing routing table successful" }, - { re: "TSF:LRT:OK", d: "Loading routing table successful" }, - { re: "TSF:SRT:OK", d: "Saving routing table successful" }, - { re: "!TSF:RTE:FPAR ACTIVE", d: "Finding parent active, message not sent" }, - { re: "!TSF:RTE:DST (\\d+) UNKNOWN", d: "Routing for destination $1 unknown, sending message to parent" }, - { re: "!TSF:RTE:N2N FAIL", d: "Direct node-to-node communication failed - handing over to parent" }, - { re: "TSF:RRT:ROUTE N=(\\d+),R=(\\d+)", d: "Routing table, messages to node ($1) are routed via node ($2)"}, - { re: "!TSF:SND:TNR", d: "Transport not ready, message cannot be sent" }, - { re: "TSF:TDI:TSL", d: "Set transport to sleep" }, - { re: "TSF:TDI:TPD", d: "Power down transport" }, - { re: "TSF:TRI:TRI", d: "Reinitialise transport" }, - { re: "TSF:TRI:TSB", d: "Set transport to standby" }, - { re: "TSF:TRI:TPU", d: "Power up transport" }, - { re: "TSF:SIR:CMD=(\\d+),VAL=(\\d+)", d: "Get signal report $1, value: $2" }, - { re: "TSF:MSG:READ,(\\d+)-(\\d+)-(\\d+),s=(\\d+),c=(\\d+),t=(\\d+),pt=(\\d+),l=(\\d+),sg=(\\d+):(.*)", d: "Received Message
Sender: $1
Last Node: $2
Destination: $3
Sensor Id: $4
Command: {command:$5}
Message Type: {type:$5:$6}
Payload Type: {pt:$7}
Payload Length: $8
Signing: $9
Payload: $10" }, - { re: "TSF:MSG:SEND,(\\d+)-(\\d+)-(\\d+)-(\\d+),s=(\\d+),c=(\\d+),t=(\\d+),pt=(\\d+),l=(\\d+),sg=(\\d+),ft=(\\d+),st=(\\w+):(.*)", d: "Sent Message
Sender: $1
Last Node: $2
Next Node: $3
Destination: $4
Sensor Id: $5
Command: {command:$6}
Message Type:{type:$6:$7}
Payload Type: {pt:$8}
Payload Length: $9
Signing: $10
Failed uplink counter: $11
Status: $12 (OK=success, NACK=no radio ACK received)
Payload: $13" }, - { re: "!TSF:MSG:SEND,(\\d+)-(\\d+)-(\\d+)-(\\d+),s=(\\d+),c=(\\d+),t=(\\d+),pt=(\\d+),l=(\\d+),sg=(\\d+),ft=(\\d+),st=(\\w+):(.*)", d: "Sent Message
Sender: $1
Last Node: $2
Next Node: $3
Destination: $4
Sensor Id: $5
Command: {command:$6}
Message Type:{type:$6:$7}
Payload Type: {pt:$8}
Payload Length: $9
Signing: $10
Failed uplink counter: $11
Status: $12 (OK=success, NACK=no radio ACK received)
Payload: $13" }, - { re: "\\?TSF:MSG:SEND,(\\d+)-(\\d+)-(\\d+)-(\\d+),s=(\\d+),c=(\\d+),t=(\\d+),pt=(\\d+),l=(\\d+),sg=(\\d+),ft=(\\d+),st=(\\w+):(.*)", d: "Sent Message without radio ACK
Sender: $1
Last Node: $2
Next Node: $3
Destination: $4
Sensor Id: $5
Command: {command:$6}
Message Type:{type:$6:$7}
Payload Type: {pt:$8}
Payload Length: $9
Signing: $10
Failed uplink counter: $11
Status: $12 (OK=success, NACK=no radio ACK received)
Payload: $13" }, - - // transport HAL - - { re: "THA:INIT", d: "Initialise transport HAL" }, - { re: "THA:INIT:PSK=(.*)", d: "Initialise transport HAL, PSK=$1" }, - { re: "THA:SAD:ADDR=(\\d+)", d: "Set transport address: $1" }, - { re: "THA:GAD:ADDR=(\\d+)", d: "Get transport address: $1" }, - { re: "THA:DATA:AVAIL", d: "Transport HAL received data" }, - { re: "THA:SAN:RES=(\\d+)", d: "Transport sanity check, result=$1 (0=NOK, 1=OK)" }, - { re: "THA:RCV:MSG=(.*)", d: "Message received: $1" }, - { re: "THA:RCV:DECRYPT", d: "Decrypt message" }, - { re: "THA:RCV:PLAIN=(.*)", d: "Message plaint text: $1" }, - { re: "!THA:RCV:PVER=(\\d+)", d: "Message protocol version mismatch: $1" }, - { re: "!THA:RCV:LEN=(\\d+),EXP=(\\d+)", d: "Invalid message length, actual $1, expected $2" }, - { re: "THA:RCV:MSG LEN=(\\d+)", d: "Length of received message: $1" }, - { re: "THA:SND:MSG=(.*)", d: "Send message: $1" }, - { re: "THA:SND:ENCRYPT", d: "Encrypt message" }, - { re: "THA:SND:CIP=(.*)", d: "Ciphertext of encrypted message: $1" }, - { re: "THA:SND:MSG LEN=(\\d+),RES=(\\d+)", d: "Sending message with length=$1, result=$2 (0=NOK, 1=OK)" }, - - // Signing backend - - { re: "SGN:INI:BND OK", d: "Backend has initialized ok" }, - { re: "!SGN:INI:BND FAIL", d: "Backend has not initialized ok" }, - { re: "SGN:PER:OK", d: "Personalization data is ok" }, - { re: "!SGN:PER:TAMPERED", d: "Personalization data has been tampered" }, - { re: "SGN:PRE:SGN REQ", d: "Signing required" }, - { re: "SGN:PRE:SGN REQ,TO=(\\d+)", d: "Tell node $1 that we require signing" }, - { re: "SGN:PRE:SGN REQ,FROM=(\\d+)", d: " Node $1 require signing" }, - { re: "SGN:PRE:SGN NREQ", d: "Signing not required" }, - { re: "SGN:PRE:SGN REQ,TO=(\\d+)", d: "Tell node $1 that we do not require signing" }, - { re: "SGN:PRE:SGN NREQ,FROM=(\\d+)", d: "Node $1 does not require signing" }, - { re: "!SGN:PRE:SGN NREQ,FROM=(\\d+) REJ", d: "Node $1 does not require signing but used to (requirement remain unchanged)" }, - { re: "SGN:PRE:WHI REQ", d: "Whitelisting required" }, - { re: "SGN:PRE:WHI REQ;TO=(\\d+)", d: "Tell $1 that we require whitelisting" }, - { re: "SGN:PRE:WHI REQ,FROM=(\\d+)", d: "Node $1 require whitelisting" }, - { re: "SGN:PRE:WHI NREQ", d: " Whitelisting not required" }, - { re: "SGN:PRE:WHI NREQ,TO=(\\d+)", d: "Tell node $1 that we do not require whitelisting" }, - { re: "SGN:PRE:WHI NREQ,FROM=(\\d+)", d: "Node $1 does not require whitelisting" }, - { re: "!SGN:PRE:WHI NREQ,FROM=(\\d+) REJ", d: "Node $1 does not require whitelisting but used to (requirement remain unchanged)" }, - { re: "SGN:PRE:XMT,TO=(\\d+)", d: "Presentation data transmitted to node $1" }, - { re: "!SGN:PRE:XMT,TO=(\\d+) FAIL", d: "Presentation data not properly transmitted to node $1" }, - { re: "SGN:PRE:WAIT GW", d: "Waiting for gateway presentation data" }, - { re: "!SGN:PRE:VER=(\\d+)", d: "Presentation version $1 is not supported" }, - { re: "SGN:PRE:NSUP", d: "Received signing presentation but signing is not supported" }, - { re: "SGN:PRE:NSUP,TO=(\\d+)", d: "Informing node $1 that we do not support signing" }, - { re: "SGN:SGN:NCE REQ,TO=(\\d+)", d: "Nonce request transmitted to node $1" }, - { re: "!SGN:SGN:NCE REQ,TO=(\\d+) FAIL", d: "Nonce request not properly transmitted to node $1" }, - { re: "!SGN:SGN:NCE TMO", d: "Timeout waiting for nonce" }, - { re: "SGN:SGN:SGN", d: "Message signed" }, - { re: "!SGN:SGN:SGN FAIL", d: "Message failed to be signed" }, - { re: "SGN:SGN:NREQ=(\\d+)", d: "Node $1 does not require signed messages" }, - { re: "SGN:SGN:(\\d+)!=(\\d+) NUS", d: "Will not sign because $1 is not $2 (repeater)" }, - { re: "!SGN:SGN:STATE", d: "Security system in a invalid state (personalization data tampered)" }, - { re: "!SGN:VER:NSG", d: "Message was not signed, but it should have been" }, - { re: "!SGN:VER:FAIL", d: "Verification failed" }, - { re: "SGN:VER:OK", d: "Verification succeeded" }, - { re: "SGN:VER:LEFT=(\\d+)", d: "$1 number of failed verifications left in a row before node is locked" }, - { re: "!SGN:VER:STATE", d: "Security system in a invalid state (personalization data tampered)" }, - { re: "SGN:SKP:MSG CMD=(\\d+),TYPE=(\\d+)", d: "Message with command $1 and type $2 does not need to be signed" }, - { re: "SGN:SKP:ECHO CMD=(\\d+),TYPE=(\\d+)", d: "ECHO messages do not need to be signed" }, - { re: "SGN:NCE:LEFT=(\\d+)", d: "$1 number of nonce requests between successful verifications left before node is locked" }, - { re: "SGN:NCE:XMT,TO=(\\d+)", d: "Nonce data transmitted to node $1" }, - { re: "!SGN:NCE:XMT,TO=(\\d+) FAIL", d: "Nonce data not properly transmitted to node $1" }, - { re: "!SGN:NCE:GEN", d: "Failed to generate nonce" }, - { re: "SGN:NCE:NSUP (DROPPED)", d: "Ignored nonce/request for nonce (signing not supported)" }, - { re: "SGN:NCE:FROM=(\\d+)", d: "Received nonce from node $1" }, - { re: "SGN:NCE:(\\d+)!=(\\d+) (DROPPED)", d: "Ignoring nonce as it did not come from the desgination of the message to sign" }, - { re: "!SGN:BND:INIT FAIL", d: "Failed to initialize signing backend" }, - { re: "!SGN:BND:PWD<8", d: "Signing password too short" }, - { re: "!SGN:BND:PER", d: "Backend not personalized" }, - { re: "!SGN:BND:SER", d: "Could not get device unique serial from backend" }, - { re: "!SGN:BND:TMR", d: "Backend timed out" }, - { re: "!SGN:BND:SIG,SIZE,(\\d+)>(\\d+)", d: "Refusing to sign message with length $1 because it is bigger than allowed size $2 " }, - { re: "SGN:BND:SIG WHI,ID=(\\d+)", d: "Salting message with our id $1" }, - { re: "SGN:BND:SIG WHI,SERIAL=(.*)", d: "Salting message with our serial $1" }, - { re: "!SGN:BND:VER ONGOING", d: "Verification failed, no ongoing session" }, - { re: "!SGN:BND:VER,IDENT=(\\d+)", d: "Verification failed, identifier $1 is unknown" }, - { re: "SGN:BND:VER WHI,ID=(\\d+)", d: "Id $1 found in whitelist" }, - { re: "SGN:BND:VER WHI,SERIAL=(.*)", d: "Expecting serial $1 for this sender" }, - { re: "!SGN:BND:VER WHI,ID=(\\d+) MISSING", d: "Id $1 not found in whitelist" }, - { re: "SGN:BND:NONCE=(.*)", d: "Calculating signature using nonce $1" }, - { re: "SGN:BND:HMAC=(.*)", d: "Calculated signature is $1" }, - - // NodeManager - - { re: "NM:INIT:VER=(.*)", d: "NodeManager version $1" }, - { re: "NM:INIT:INO=(.*)", d: "Sketch $1" }, - { re: "NM:INIT:LIB VER=(.+) CP=(.+)", d: "MySensors Library version $1, capabilities $2" }, - { re: "NM:INIT:RBT p=(\\d+)", d: "Configured reboot pin $1" }, - { re: "NM:BFR:INIT", d: "Connecting to the gateway..." }, - { re: "NM:BFR:OK", d: "Connection to the gateway successful" }, - { re: "NM:BFR:INT p=(\\d+) m=(\\d+)", d: "Setting up interrupt on pin $1 with mode $2" }, - { re: "NM:PRES:(\\w+)\\((\\d+)\\) p=(\\d+) t=(\\d+)", d: "Presented to the gateway child $2 for sensor $1 as {type:0:$3} with type {type:1:$4}" }, - { re: "NM:STP:ID=(\\d+) M=(\\d+)", d: "This node has id $1 and metric is set to $2" }, - { re: "NM:STP:SD T=(\\d+)", d: "Connected SD card reader, type $1" }, - { re: "NM:STP:HW V=(\\d+) F=(\\d+) M=(\\d+)", d: "CPU Vcc is $1 mV, CPU frequency $2 Mhz, free memory $3 bytes" }, - { re: "NM:LOOP:(\\w+)\\((\\d+)\\):SET t=(\\d+) v=(.+)", d: "New value for child $2 of sensor $1 with {type:1:$3} = $4" }, - { re: "NM:LOOP:INT p=(\\d+) v=(\\d+)", d: "Interrupt received on pin $1, value $2" }, - { re: "NM:LOOP:INPUT\\.\\.\\.", d: "Waiting for input from the serial port" }, - { re: "NM:LOOP:INPUT v=(.*)", d: "Received an input from the serial port: $1" }, - { re: "NM:TIME:REQ", d: "Requesting the time to the controller" }, - { re: "NM:TIME:OK ts=(\\d+)", d: "Received the time from the controller: $1" }, - { re: "NM:SLP:WKP", d: "Wakeup requested" }, - { re: "NM:SLP:SLEEP s=(\\d+)", d: "Going to sleep for $1 seconds" }, - { re: "NM:SLP:AWAKE", d: "Waking up from sleep" }, - { re: "NM:SLP:LOAD s=(\\d+)", d: "Loaded configured sleep time: $1 seconds" }, - { re: "NM:MSG:SEND\\((\\d+)\\) t=(\\d+) p=(.+)", d: "Child $1 sent {type:1:$2} = $3" }, - { re: "NM:MSG:RECV\\((\\d+)\\) c=(\\d+) t=(\\d+) p=(.+)", d: "Received a {command:$2} message for child $1 with {type:$2:$3} = $4" }, - { re: "NM:PWR:RBT", d: "Rebooting the node as requested" }, - { re: "NM:PWR:ON p=(\\d+)", d: "Powering on the sensor(s) through pin $1" }, - { re: "NM:PWR:OFF p=(\\d+)", d: "Powering off the sensor(s) through pin $1" }, - { re: "NM:OTA:REQ f=(\\d+) v=(\\d+)", d: "Over-the-air configuration change requested, function $1 value $2" }, - { re: "NM:EEPR:CLR", d: "Clearing the EEPROM as requested" }, - { re: "NM:EEPR:LOAD i=(\\d+) v=(\\d+)", d: "Read from EEPROM at position $1 the value $2" }, - { re: "NM:EEPR:SAVE i=(\\d+) v=(\\d+)", d: "Wrote to EEPROM at position $1 the value $2" }, - { re: "NM:EEPR:(\\w+)\\((\\d+)\\):LOAD", d: "Restoring from EEPROM the value of child $2 of sensor $1" }, - { re: "NM:EEPR:(\\w+)\\((\\d+)\\):SAVE", d: "Saving to EEPROM the value of child $2 of sensor $1$1: $2" }, - { re: "!NM:SENS:([^:]+):(.+)", d: "Error in sensor $1: $2" }, -]; - - - -// Init regexes -for (var i=0, len=match.length;i0xA0 -#ifndef MY_OTA_I2C_ADDR -#define MY_OTA_I2C_ADDR 0x50 -#endif -#endif - - -/** - * @defgroup TransportSettingGrpPub Transport selection - * @ingroup MyConfigGrp - * @brief These options control what transport type to use and various transport specific customisations. - * @{ - */ - - -/** - * @defgroup RS485SettingGrpPub RS485 - * @ingroup TransportSettingGrpPub - * @brief These options are specific to the RS485 wired transport. - * @{ - */ - -/** - * @def MY_RS485 - * @brief Define this to use the RS485 wired transport for sensor network communication. - */ -//#define MY_RS485 - -/** - * @def MY_RS485_BAUD_RATE - * @brief The RS485 BAUD rate. - */ -#ifndef MY_RS485_BAUD_RATE -#define MY_RS485_BAUD_RATE (9600) -#endif - -/** - * @def MY_RS485_MAX_MESSAGE_LENGTH - * @brief The maximum message length used for RS485. - */ -#ifndef MY_RS485_MAX_MESSAGE_LENGTH -#define MY_RS485_MAX_MESSAGE_LENGTH (40) -#endif - -/** - * @def MY_RS485_SOH_COUNT - * @brief Use this in case of collisions on the bus. 3 might be a good setting. - */ -#ifndef MY_RS485_SOH_COUNT -#define MY_RS485_SOH_COUNT (1) -#endif - - -/** - * @def MY_RS485_DE_PIN - * @brief RS485 driver enable pin. - */ -//#define MY_RS485_DE_PIN (2) - -/** - * @def MY_RS485_DE_INVERSE - * @brief Define this if RS485 driver enable pin polarity is inverted (low-active). - */ -//#define MY_RS485_DE_INVERSE - -/** - * @def MY_RS485_HWSERIAL - * @brief Define this if RS485 is connected to a hardware serial port. - * - * Example: @code #define MY_RS485_HWSERIAL Serial1 @endcode - */ -//#define MY_RS485_HWSERIAL (Serial1) -/** @}*/ // End of RS485SettingGrpPub group - -/** - * @defgroup RF24SettingGrpPub RF24 - * @ingroup TransportSettingGrpPub - * @brief These options are specific to the RF24 family of wireless transport modules. - * - * The following chips are supported by this driver: - * | Vendor | Chip - * |--------------------------|---------- - * | Nordic Semiconductor | nRF24L01 - * | | nRF24L01+ - * | Beken Corporation | BK2401 - * | | BK2421 - * | | BK2491 - * | Hope Microelectronics | RFM70 - * | | RFM73 - * | Panchip Microelectronics | XN297 - * | Silicon Labs(?) | SI24R1 - * @{ - */ - -// legacy - remove for 3.0.0 -/** -* @def MY_RADIO_NRF24 -* @brief Define this to use a RF24-based radio transport for sensor network communication. -* @deprecated This flag is deprecated and replaced by @ref MY_RADIO_RF24 -*/ -#ifdef MY_RADIO_NRF24 -#warning MY_RADIO_NRF24 is deprecated, use MY_RADIO_RF24 instead. -#undef MY_RADIO_NRF24 -#define MY_RADIO_RF24 -#endif - -/** - * @def MY_RADIO_RF24 - * @brief Define this to use a RF24-based radio transport for sensor network communication. - */ -//#define MY_RADIO_RF24 - -/** - * @def MY_RF24_ENABLE_ENCRYPTION - * @brief Define this to enable software based %AES encryption. - * - * All nodes and gateway must have this enabled, and all must be personalized with the same %AES - * key. - * @see @ref personalization - * - * @warning This driver always sets the initialization vector to 0 so encryption is weak. - */ -//#define MY_RF24_ENABLE_ENCRYPTION - -/** - * @def MY_DEBUG_VERBOSE_RF24 - * @brief Define this for verbose debug prints related to the RF24 driver. - */ -//#define MY_DEBUG_VERBOSE_RF24 - -/** - * @def MY_RF24_SPI_SPEED - * @brief Define this if you need to run the SPI clock at a different frequency than the default. - * - * Default nRF24L01+ SPI speed, 2MHz should be safe for nRF24L01+ clones. - */ -#ifndef MY_RF24_SPI_SPEED -#define MY_RF24_SPI_SPEED (2*1000000ul) -#endif - -/** - * @def MY_RF24_CE_PIN - * @brief Define this to change the chip enable pin from the default. - */ -#ifndef MY_RF24_CE_PIN -#define MY_RF24_CE_PIN (DEFAULT_RF24_CE_PIN) -#endif - -/** - * @def MY_RF24_CS_PIN - * @brief Define this to change the chip select pin from the default. - */ -#ifndef MY_RF24_CS_PIN -#define MY_RF24_CS_PIN (DEFAULT_RF24_CS_PIN) -#endif - -/** - * @def MY_RF24_IRQ_PIN - * @brief Define this to use the IRQ pin of the RF24 module (optional). - */ -//#define MY_RF24_IRQ_PIN (2) - -/** - * @def MY_RF24_POWER_PIN - * @brief Define this to use the RF24 power pin (optional). - */ -//#define MY_RF24_POWER_PIN (3) - -/** - * @def MY_RX_MESSAGE_BUFFER_FEATURE - * @brief This enables the receiving buffer feature. - * - * This feature is currently not supported for anything but RF24. - * Require @ref MY_RF24_IRQ_PIN to be set. - * - * Note: Not supported on ESP8266, ESP32, STM32, nRF5 and sketches - * that use SoftSPI. See below issue for details - * https://github.com/mysensors/MySensors/issues/1128 - */ -//#define MY_RX_MESSAGE_BUFFER_FEATURE - -/** - * @def MY_RX_MESSAGE_BUFFER_SIZE - * @brief Define this to change the incoming message buffer size from the default. - * - * Require @ref MY_RX_MESSAGE_BUFFER_FEATURE to be set. - */ -#ifdef MY_RX_MESSAGE_BUFFER_FEATURE -#ifndef MY_RX_MESSAGE_BUFFER_SIZE -#define MY_RX_MESSAGE_BUFFER_SIZE (20) -#endif -#endif - -/** - * @def MY_RF24_PA_LEVEL - * @brief Default RF24 PA level. Override in sketch if needed. - * - * - RF24_PA_MIN = -18dBm - * - RF24_PA_LOW = -12dBm - * - RF24_PA_HIGH = -6dBm - * - RF24_PA_MAX = 0dBm - */ -#ifndef MY_RF24_PA_LEVEL -#define MY_RF24_PA_LEVEL (RF24_PA_HIGH) -#endif - -/** - * @def MY_RF24_CHANNEL - * @brief RF channel for the sensor net, 0-125. - * - * Frequencies: 2400 Mhz - 2525 Mhz - * - * Channels: 126 - * @see https://www.nordicsemi.com/eng/nordic/download_resource/8765/2/42877161/2726 - * - * - 0 => 2400 Mhz (RF24 channel 1) - * - 1 => 2401 Mhz (RF24 channel 2) - * - 76 => 2476 Mhz (RF24 channel 77) - * - 83 => 2483 Mhz (RF24 channel 84) - * - 124 => 2524 Mhz (RF24 channel 125) - * - 125 => 2525 Mhz (RF24 channel 126) - * - * In some countries there might be limitations, in Germany for example only the range - * 2400,0 - 2483,5 Mhz is allowed. - * @see http://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Telekommunikation/Unternehmen_Institutionen/Frequenzen/Allgemeinzuteilungen/2013_10_WLAN_2,4GHz_pdf.pdf - */ -#ifndef MY_RF24_CHANNEL -#define MY_RF24_CHANNEL (76) -#endif - -/** - * @def MY_RF24_DATARATE - * @brief RF24 data rate. - * - * - RF24_250KBPS for 250kbs - * - RF24_1MBPS for 1Mbps - * - RF24_2MBPS for 2Mbps. - * - * @note nRF24L01, BK2401, BK2421, BK2491 and XN297 does not support RF24_250KBPS - * @note BK2401 does not support RF24_2MBPS - */ -#ifndef MY_RF24_DATARATE -#define MY_RF24_DATARATE (RF24_250KBPS) -#endif - -/** - * @def MY_RF24_BASE_RADIO_ID - * @brief RF24 radio network identifier. - * - * This acts as base value for sensor nodeId addresses. Change this (or channel) if you have more - * than one sensor network. - */ -#ifndef MY_RF24_BASE_RADIO_ID -#define MY_RF24_BASE_RADIO_ID 0x00,0xFC,0xE1,0xA8,0xA8 -#endif - -/** - * @def MY_RF24_ADDR_WIDTH - * @brief RF24 base address width. - */ -#ifndef MY_RF24_ADDR_WIDTH -#define MY_RF24_ADDR_WIDTH (5) -#endif -/** @}*/ // End of RF24SettingGrpPub group - -/** - * @defgroup NRF5SettingGrpPub nRF5 - * @ingroup TransportSettingGrpPub - * @brief These options are specific to the nRF5 (with Enhanced ShockBurst) family of wireless - * transport modules. - * - * The nRF5 driver is OTA compatible with the RF24 driver. - * - * The following chips are supported by this driver: - * - nRF51x22 - * - nRF52822 - * - * @{ - */ - -/** - * @def MY_RADIO_NRF5_ESB - * @brief Define this to use nRF5 based radios for sensor network communication. - * - * @see ARDUINO_ARCH_NRF5 - */ -//#define MY_RADIO_NRF5_ESB - -/** - * @def MY_NRF5_ESB_ENABLE_ENCRYPTION - * @brief Define this to enable software based (RF24 compatible) %AES encryption. - * - * All nodes and gateway must have this enabled, and all must be personalized with the same %AES - * key. - * @see @ref personalization - * - * @warning This driver always sets the initialization vector to 0 so encryption is weak. - */ -//#define MY_NRF5_ESB_ENABLE_ENCRYPTION - -/** - * @def MY_DEBUG_VERBOSE_NRF5_ESB - * @brief Define this for verbose debug prints related to the nRF5 driver. - */ -//#define MY_DEBUG_VERBOSE_NRF5_ESB - -/** - * @def MY_NRF5_ESB_PA_LEVEL - * @brief Default nRF5 PA level. Override in sketch if needed. - * - * - NRF5_PA_MIN = -40dBm - * - NRF5_PA_LOW = -16dBm - * - NRF5_PA_HIGH = 0dBm - * - NRF5_PA_MAX = 4dBm - */ -#ifndef MY_NRF5_ESB_PA_LEVEL -#define MY_NRF5_ESB_PA_LEVEL (NRF5_PA_MAX) -#endif - -/** - * @def MY_NRF5_ESB_CHANNEL - * @brief RF channel for the sensor net, 0-125. - * - * Frequencies: 2400 Mhz - 2525 Mhz - * - * Channels: 126 - * @see https://www.nordicsemi.com/eng/nordic/download_resource/8765/2/42877161/2726 - * - * - 0 => 2400 Mhz (RF24 channel 1) - * - 1 => 2401 Mhz (RF24 channel 2) - * - 76 => 2476 Mhz (RF24 channel 77) - * - 83 => 2483 Mhz (RF24 channel 84) - * - 124 => 2524 Mhz (RF24 channel 125) - * - 125 => 2525 Mhz (RF24 channel 126) - * - * In some countries there might be limitations, in Germany for example only the range - * 2400,0 - 2483,5 Mhz is allowed. - * @see http://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Telekommunikation/Unternehmen_Institutionen/Frequenzen/Allgemeinzuteilungen/2013_10_WLAN_2,4GHz_pdf.pdf - */ -#ifndef MY_NRF5_ESB_CHANNEL -#define MY_NRF5_ESB_CHANNEL (76) -#endif - -/** - * @def MY_NRF5_ESB_MODE - * @brief nRF5 mode. - * - * - NRF5_250KBPS for 250kbs (Deprecated) - * - NRF5_1MBPS for 1Mbps - * - NRF5_2MBPS for 2Mbps. - * - NRF5_BLE_1MBPS for 1Mbps BLE modulation - */ -#ifndef MY_NRF5_ESB_MODE -#define MY_NRF5_ESB_MODE (NRF5_250KBPS) -#endif - -/** - * @def MY_NRF5_ESB_BASE_RADIO_ID - * @brief nRF5 radio network identifier. - * - * This acts as base value for sensor nodeId addresses. Change this (or channel) if you have more - * than one sensor network. - */ -#ifndef MY_NRF5_ESB_BASE_RADIO_ID -#define MY_NRF5_ESB_BASE_RADIO_ID 0x00, 0xFC, 0xE1, 0xA8, 0xA8 -#endif - -/** - * @def MY_NRF5_ESB_ADDR_WIDTH - * @brief nRF5 base address width. - */ -#ifndef MY_NRF5_ESB_ADDR_WIDTH -#define MY_NRF5_ESB_ADDR_WIDTH (5) -#endif - -/** - * @def MY_NRF5_ESB_RX_BUFFER_SIZE - * @brief Declare the amount of incoming messages that can be buffered at driver level. - */ -#ifndef MY_NRF5_ESB_RX_BUFFER_SIZE -#define MY_NRF5_ESB_RX_BUFFER_SIZE (20) -#endif - -/** - * @def MY_NRF5_ESB_REVERSE_ACK_TX - * @brief Switch to SI24R1 or faked nRF24L01+ compatible ACK mode. ACK bit is reversed on TX side. - */ -//#define MY_NRF5_ESB_REVERSE_ACK_TX - -/** - * @def MY_NRF5_ESB_REVERSE_ACK_RX - * @brief Switch to SI24R1 or faked nRF24L01+ compatible ACK mode. ACK bit is reversed on RX side. - */ -//#define MY_NRF5_ESB_REVERSE_ACK_RX -/** @}*/ // End of NRF5SettingGrpPub group - -/** - * @defgroup RFM69SettingGrpPub RFM69 - * @ingroup TransportSettingGrpPub - * @brief These options are specific to the %RFM69 family of wireless transport modules. - * - * The following chips are supported by this driver: - * - Semtech sx1231 - * - * If using the HW variant of the %RFM69 module, define @ref MY_IS_RFM69HW. - * @{ - */ - -/** - * @def MY_RADIO_RFM69 - * @brief Define this to use %RFM69 based radios for sensor network communication. - */ -//#define MY_RADIO_RFM69 - -/** - * @def MY_DEBUG_VERBOSE_RFM69 - * @brief Define this for verbose debug prints related to the %RFM69 driver. - */ -//#define MY_DEBUG_VERBOSE_RFM69 - -/** - * @def MY_DEBUG_VERBOSE_RFM69_REGISTERS - * @brief Define this for verbose dumping of the %RFM69 registers. - */ -//#define MY_DEBUG_VERBOSE_RFM69_REGISTERS - -/** - * @def MY_RFM69_NEW_DRIVER - * @brief Define this to enable the improved %RFM69 driver. - * - * @note This driver is not compatible with the old (=default) %RFM69 driver. - */ -//#define MY_RFM69_NEW_DRIVER - -/** - * @def MY_RFM69_FREQUENCY - * @brief The frequency to use. - * - * - RFM69_315MHZ - * - RFM69_433MHZ - * - RFM69_865MHZ - * - RFM69_868MHZ - * - RFM69_915MHZ - * - Custom frequency in Hz (new %RFM69 driver only) - * @see MY_RFM69_NEW_DRIVER - * - * This must match the hardware version of the %RFM69 radio. - * Additional information: https://en.wikipedia.org/wiki/Short_Range_Devices - */ -#ifndef MY_RFM69_FREQUENCY -#define MY_RFM69_FREQUENCY (RFM69_868MHZ) -#endif - -/** - * @def MY_IS_RFM69HW - * @brief Define this if you are using the RFM69HW model. - */ -//#define MY_IS_RFM69HW - -/** - * @def MY_RFM69HW - * @brief Set to true if @ref MY_IS_RFM69HW is set. - * - * @todo Mark this internals - */ -#ifdef MY_IS_RFM69HW -#define MY_RFM69HW true -#else -#define MY_RFM69HW false -#endif - -/** - * @def MY_RFM69_TX_POWER_DBM - * @brief Set TX power level, default 5dBm (overridden if ATC mode enabled). - */ -#ifndef MY_RFM69_TX_POWER_DBM -#define MY_RFM69_TX_POWER_DBM (5) -#endif - -/** - * @def MY_RFM69_ATC_TARGET_RSSI_DBM - * @brief Target RSSI level (in dBm) for %RFM69 ATC mode. - */ -#ifndef MY_RFM69_ATC_TARGET_RSSI_DBM -#define MY_RFM69_ATC_TARGET_RSSI_DBM (-80) -#endif - -/** - * @def MY_RFM69_ATC_MODE_DISABLED - * @brief Define to disable ATC mode of %RFM69 driver. - */ -//#define MY_RFM69_ATC_MODE_DISABLED - -/** - * @def MY_RFM69_MAX_POWER_LEVEL_DBM - * @brief Set max TX power in dBm if local legislation requires this - * - * - 1mW = 0dBm - * - 10mW = 10dBm - * - 25mW = 14dBm - * - 100mW = 20dBm - * - * See here: https://en.wikipedia.org/wiki/Short_Range_Devices - */ -//#define MY_RFM69_MAX_POWER_LEVEL_DBM (10u) - -/** - * @def MY_RFM69_NETWORKID - * @brief %RFM69 Network ID. Use the same for all nodes that will talk to each other. - */ -#ifndef MY_RFM69_NETWORKID -#define MY_RFM69_NETWORKID (100) -#endif - -/** - * @def MY_RFM69_RST_PIN - * @brief Define this to use the %RFM69 reset pin (optional). - */ -//#define MY_RFM69_RST_PIN (9) - -#ifdef MY_RF69_RESET -#warning MY_RF69_RESET is depreciated, please use MY_RFM69_RST_PIN instead. -#define MY_RFM69_RST_PIN MY_RF69_RESET -#endif - -/** - * @def MY_RFM69_POWER_PIN - * @brief Define this to use the %RFM69 power pin (optional). - */ -//#define MY_RFM69_POWER_PIN (3) - -/** - * @def MY_RFM69_IRQ_PIN - * @brief Define this to override the default %RFM69 IRQ pin assignment. - */ -#ifndef MY_RFM69_IRQ_PIN -#ifdef MY_RF69_IRQ_PIN -#warning MY_RF69_IRQ_PIN is depreciated, please use MY_RFM69_IRQ_PIN instead. -#define MY_RFM69_IRQ_PIN MY_RF69_IRQ_PIN -#else -#define MY_RFM69_IRQ_PIN DEFAULT_RFM69_IRQ_PIN -#endif -#endif - -/** - * @def MY_RFM69_IRQ_NUM - * @brief %RFM69 IRQ number. - */ -#ifndef MY_RFM69_IRQ_NUM -#ifdef MY_RF69_IRQ_NUM -#warning MY_RF69_IRQ_NUM is depreciated, please use MY_RFM69_IRQ_NUM instead. -#define MY_RFM69_IRQ_NUM MY_RF69_IRQ_NUM -#else -#define MY_RFM69_IRQ_NUM digitalPinToInterrupt(MY_RFM69_IRQ_PIN) -#endif -#endif - -/** - * @def MY_RFM69_CS_PIN - * @brief %RFM69 SPI chip select pin. - */ -#ifndef MY_RFM69_CS_PIN -#ifdef MY_RF69_SPI_CS -#warning MY_RF69_SPI_CS is depreciated, please use MY_RFM69_CS_PIN instead. -#define MY_RFM69_CS_PIN MY_RF69_SPI_CS -#else -#define MY_RFM69_CS_PIN DEFAULT_RFM69_CS_PIN -#endif -#endif - -/** - * @def MY_RFM69_SPI_SPEED - * @brief Set to overrule default RFM69 SPI speed. - */ -#ifndef MY_RFM69_SPI_SPEED -#define MY_RFM69_SPI_SPEED (4*1000000ul) // datasheet says 10Mhz max. -#endif - -/** - * @def MY_RFM69_ENABLE_ENCRYPTION - * @brief Define this to enable %AES encryption in the %RFM69 module. - * - * All nodes and gateway must have this enabled, and all must be personalized with the same %AES - * key. - * @see @ref personalization - */ -//#define MY_RFM69_ENABLE_ENCRYPTION - -/** - * @def MY_RFM69_MODEM_CONFIGURATION - * @brief %RFM69 modem configuration, default is %RFM69_FSK_BR55_5_FD50 - * - * | Configuration | Modulation (xxx) | Bit rate | FD | RXBW | Additional settings - * |-------------------------|------------------|----------|--------|----------|--------------------------- - * | RFM69_xxx_BR2_FD5 | FSK/GFSK/OOK | 2000 | 5000 | 111_24_4 | Whitening - * | RFM69_xxx_BR2_4_FD4_8 | FSK/GFSK/OOK | 2400 | 4800 | 111_24_4 | Whitening - * | RFM69_xxx_BR4_8_FD9_6 | FSK/GFSK/OOK | 4800 | 9600 | 111_24_4 | Whitening - * | RFM69_xxx_BR9_6_FD19_2 | FSK/GFSK/OOK | 9600 | 19200 | 111_24_4 | Whitening - * | RFM69_xxx_BR19_2_FD38_4 | FSK/GFSK/OOK | 19200 | 38400 | 111_24_3 | Whitening - * | RFM69_xxx_BR38_4_FD76_8 | FSK/GFSK/OOK | 38400 | 76800 | 111_24_2 | Whitening - * | RFM69_xxx_BR55_5_FD50 | FSK/GFSK/OOK | 55555 | 50000 | 111_16_2 | Whitening - * | RFM69_xxx_BR57_6_FD120 | FSK/GFSK/OOK | 57600 | 120000 | 111_16_1 | Whitening - * | RFM69_xxx_BR125_FD125 | FSK/GFSK/OOK | 125000 | 125000 | 010_16_2 | Whitening - * | RFM69_xxx_BR250_FD250 | FSK/GFSK/OOK | 250000 | 250000 | 111_16_0 | Whitening - * - * https://www.semtech.com/uploads/documents/sx1231.pdf - * - */ -//#define MY_RFM69_MODEM_CONFIGURATION (RFM69_FSK_BR55_5_FD50) - - -/** @}*/ // End of RFM69SettingGrpPub group - -/** - * @defgroup RFM95SettingGrpPub RFM95 - * @ingroup TransportSettingGrpPub - * @brief These options are specific to the %RFM95 family of wireless transport modules. - * - * The following chips are supported by this driver: - * - Semtech sx1276 - * @{ - */ - -/** - * @def MY_RADIO_RFM95 - * @brief Define this to use RFM95 based radios for sensor network communication. - */ -//#define MY_RADIO_RFM95 - -/** - * @def MY_DEBUG_VERBOSE_RFM95 - * @brief Define this for verbose debug prints related to the RFM95 driver. - */ -//#define MY_DEBUG_VERBOSE_RFM95 - -/** - * @def MY_RFM95_ENABLE_ENCRYPTION - * @brief Define this to enable software based %AES encryption. - * - * All nodes and gateway must have this enabled, and all must be personalized with the same %AES - * key. - * @see @ref personalization - * - * @warning This driver always sets the initialization vector to 0 so encryption is weak. - */ -//#define MY_RFM95_ENABLE_ENCRYPTION - -/** - * @def MY_RFM95_FREQUENCY - * @brief The frequency to use. - * - * - RFM95_169MHZ - * - RFM95_315MHZ - * - RFM95_434MHZ - * - RFM95_868MHZ - * - RFM95_915MHZ - * - Custom frequency in Hz - * - * This must match the hardware version of the RFM95 radio. - * Additional information: https://en.wikipedia.org/wiki/Short_Range_Devices - */ -#ifndef MY_RFM95_FREQUENCY -#define MY_RFM95_FREQUENCY (RFM95_868MHZ) -#endif - -/** - * @def MY_RFM95_MODEM_CONFIGRUATION - * @brief RFM95 modem configuration. - * - * BW = Bandwidth in kHz - * CR = Error correction code - * SF = Spreading factor, chips / symbol - * - * | CONFIG | BW | CR | SF | Comment - * |------------------------|-------|-----|------|----------------------------- - * | RFM95_BW125CR45SF128 | 125 | 4/5 | 128 | Default, medium range - * | RFM95_BW500CR45SF128 | 500 | 4/5 | 128 | Fast, short range - * | RFM95_BW31_25CR48SF512 | 31.25 | 4/8 | 512 | Slow, long range - * | RFM95_BW125CR48SF4096 | 125 | 4/8 | 4096 | Slow, long range - * - */ -#ifndef MY_RFM95_MODEM_CONFIGRUATION -#define MY_RFM95_MODEM_CONFIGRUATION RFM95_BW125CR45SF128 -#endif - -/** - * @def MY_RFM95_RST_PIN - * @brief Define this to use the RFM95 reset pin (optional). - */ -//#define MY_RFM95_RST_PIN (9) - -/** - * @def MY_RFM95_POWER_PIN - * @brief Define this to use the RFM95 power pin (optional). - */ -//#define MY_RFM95_POWER_PIN (3) - -/** - * @def MY_RFM95_IRQ_PIN - * @brief Define this to use the RFM95 IRQ pin. - */ -#ifndef MY_RFM95_IRQ_PIN -#define MY_RFM95_IRQ_PIN DEFAULT_RFM95_IRQ_PIN -#endif - -/** - * @def MY_RFM95_IRQ_NUM - * @brief RFM95 IRQ number. - */ -#ifndef MY_RFM95_IRQ_NUM -#define MY_RFM95_IRQ_NUM digitalPinToInterrupt(MY_RFM95_IRQ_PIN) -#endif - -/** - * @def MY_RFM95_CS_PIN - * @brief RFM95 SPI chip select pin. - */ -#ifndef MY_RFM95_CS_PIN -#define MY_RFM95_CS_PIN DEFAULT_RFM95_CS_PIN -#endif - -/** - * @def MY_RFM95_SPI_SPEED - * @brief Set to overrule default RFM95 SPI speed. - */ -#ifndef MY_RFM95_SPI_SPEED -#define MY_RFM95_SPI_SPEED (4*1000000ul) -#endif - -/** - * @def MY_RFM95_TX_POWER_DBM - * @brief Set TX power level, default 13dBm (overridden if ATC mode enabled) - * - * See here https://en.wikipedia.org/wiki/Short_Range_Devices - */ -#ifndef MY_RFM95_TX_POWER_DBM -#define MY_RFM95_TX_POWER_DBM (13u) // 20mW -#endif - -/** - * @def MY_RFM95_ATC_MODE_DISABLED - * @brief Define to disable ATC mode of RFM95 driver. - */ -//#define MY_RFM95_ATC_MODE_DISABLED - -/** - * @def MY_RFM95_ATC_TARGET_RSSI - * @brief Target RSSI level (in dBm) for RFM95 ATC mode - */ -#ifndef MY_RFM95_ATC_TARGET_RSSI -#define MY_RFM95_ATC_TARGET_RSSI (-70) -#endif - -/** - * @def MY_RFM95_MAX_POWER_LEVEL_DBM - * @brief Set max TX power in dBm if local legislation requires this - * - * - 1mW = 0dBm - * - 10mW = 10dBm - * - 25mW = 14dBm - * - 100mW = 20dBm - * - * See here: https://en.wikipedia.org/wiki/Short_Range_Devices - */ -//#define MY_RFM95_MAX_POWER_LEVEL_DBM (10u) - -/** - * @def MY_RFM95_TCXO - * @brief Enable to force your radio to use an external frequency source (e.g. TCXO, if present). - * - * This allows for better stability using SF 9 to 12. - */ -//#define MY_RFM95_TCXO -/** @}*/ // End of RFM95SettingGrpPub group - -/** - * @defgroup SoftSpiSettingGrpPub Soft SPI - * @ingroup TransportSettingGrpPub - * @brief These options are specific the soft SPI driver for certain radio transport drivers. - * - * The following transport drivers supported by this driver: - * - The RF24 driver @see RF24SettingGrpPub - * - The new %RFM69 driver @see RFM69SettingGrpPub @see MY_RFM69_NEW_DRIVER - * - The RFM95 driver @see RFM95SettingGrpPub - * @{ - */ - -/** - * @def MY_SOFTSPI - * @brief Define this to use a software based SPI driver which allows more freedom in pin selection - * for the (supported) radio module. - */ -//#define MY_SOFTSPI - -/** - * @def MY_SOFT_SPI_SCK_PIN - * @brief Soft SPI SCK pin. - */ -#ifndef MY_SOFT_SPI_SCK_PIN -#define MY_SOFT_SPI_SCK_PIN (14) -#endif - -/** - * @def MY_SOFT_SPI_MISO_PIN - * @brief Soft SPI MISO pin. - */ -#ifndef MY_SOFT_SPI_MISO_PIN -#define MY_SOFT_SPI_MISO_PIN (16) -#endif - -/** - * @def MY_SOFT_SPI_MOSI_PIN - * @brief Soft SPI MOSI pin. - */ -#ifndef MY_SOFT_SPI_MOSI_PIN -#define MY_SOFT_SPI_MOSI_PIN (15) -#endif -/** @}*/ // End of SoftSpiSettingGrpPub group - -/** @}*/ // End of TransportSettingGrpPub group - -/** - * @defgroup RoutingNodeSettingGrpPub Routing and node - * @ingroup MyConfigGrp - * @brief These options control message routing and node configurations. - * @{ - */ -/** - * @def MY_DISABLE_RAM_ROUTING_TABLE_FEATURE - * @ingroup memorysavings - * @brief If defined, routing table will not be kept in RAM. - * @see MY_RAM_ROUTING_TABLE_FEATURE - */ -/** - * @def MY_RAM_ROUTING_TABLE_FEATURE - * @brief If enabled, the routing table is kept in RAM (if memory allows) and saved in regular - * intervals. - * @note Enabled by default on most platforms, but on AVR only for atmega1280, atmega1284 and - * atmega2560. - * @see MY_DISABLE_RAM_ROUTING_TABLE_FEATURE - */ -#ifndef MY_DISABLE_RAM_ROUTING_TABLE_FEATURE -#define MY_RAM_ROUTING_TABLE_FEATURE -#endif - -/** - * @def MY_ROUTING_TABLE_SAVE_INTERVAL_MS - * @brief Interval to dump content of routing table to EEPROM - */ -#ifndef MY_ROUTING_TABLE_SAVE_INTERVAL_MS -#define MY_ROUTING_TABLE_SAVE_INTERVAL_MS (30*60*1000ul) -#endif - -/** - * @def MY_REPEATER_FEATURE - * @brief Enables repeater functionality (relays messages from other nodes) - * @note Repeaters need to be constantly kept awake to be useful. They are therefore not suitable - * for battery powered operation. - */ -//#define MY_REPEATER_FEATURE - -/** - * @def MY_PASSIVE_NODE - * @brief If enabled, the node operates fully autonomously, i.e. messages are sent without ACKing. - * - * @note All transport-related checks and safety-mechanisms are disabled. - * @note Requires that @ref MY_NODE_ID is set, @ref MY_PARENT_NODE_ID and - * @ref MY_PARENT_NODE_IS_STATIC are optional. - * @note Singing, registration, and OTA FW update are disabled. - */ -//#define MY_PASSIVE_NODE - -/** - * @def MY_NODE_ID - * @brief Node id defaults to AUTO (tries to fetch id from controller). - */ -#ifndef MY_NODE_ID -#define MY_NODE_ID (AUTO) -#endif - -/** - * @def MY_PARENT_NODE_ID - * @brief Node parent defaults to AUTO (tries to find a parent automatically). - */ -#ifndef MY_PARENT_NODE_ID -#define MY_PARENT_NODE_ID (AUTO) -#endif - -/** - * @def MY_PARENT_NODE_IS_STATIC - * @brief Define MY_PARENT_NODE_IS_STATIC to disable fall back if parent node fails - */ -//#define MY_PARENT_NODE_IS_STATIC - -/** - * @def MY_TRANSPORT_SANITY_CHECK - * @brief If defined, will cause node to check transport in regular intervals to detect HW issues - * and re-initialize in case of failure. - * @note This feature is enabled for all repeater nodes (incl. GW) - */ -//#define MY_TRANSPORT_SANITY_CHECK - -/** - * @def MY_TRANSPORT_SANITY_CHECK_INTERVAL_MS - * @brief Interval (in ms) for transport sanity checks - */ -#ifndef MY_TRANSPORT_SANITY_CHECK_INTERVAL_MS -#define MY_TRANSPORT_SANITY_CHECK_INTERVAL_MS (15*60*1000ul) -#endif -/** - * @def MY_TRANSPORT_DISCOVERY_INTERVAL_MS - * @brief This is a gateway-only feature: Interval (in ms) to issue network discovery checks - */ -#ifndef MY_TRANSPORT_DISCOVERY_INTERVAL_MS -#define MY_TRANSPORT_DISCOVERY_INTERVAL_MS (20*60*1000ul) -#endif - -/** - *@def MY_TRANSPORT_UPLINK_CHECK_DISABLED - *@brief If defined, disables uplink check to GW during transport initialisation - */ -//#define MY_TRANSPORT_UPLINK_CHECK_DISABLED - -/** - *@def MY_TRANSPORT_MAX_TX_FAILURES - *@brief Define to override max. consecutive TX failures until SNP is initiated - */ -//#define MY_TRANSPORT_MAX_TX_FAILURES (10u) - -/** - * @def MY_TRANSPORT_WAIT_READY_MS - * @brief Timeout in ms until transport is ready during startup, set to 0 for no timeout - */ -#ifndef MY_TRANSPORT_WAIT_READY_MS -#define MY_TRANSPORT_WAIT_READY_MS (0) -#endif - -/** -* @def MY_SIGNAL_REPORT_ENABLED -* @brief Enables signal report functionality. -* @note This feature adds ~1kB code to the sketch. -*/ -//#define MY_SIGNAL_REPORT_ENABLED - -/** @}*/ // End of RoutingNodeSettingGrpPub group - -/** - * @defgroup RegistrationSettingGrpPub Node registration - * @ingroup MyConfigGrp - * @brief These options control node registration configurations. - * @{ - */ -/** - * @def MY_REGISTRATION_FEATURE - * @brief If enabled, node has to register to GW/controller before being allowed to send sensor - * data. - * @note Enabled by default. - */ -#define MY_REGISTRATION_FEATURE - -/** - * @def MY_REGISTRATION_RETRIES - * @brief Number of registration retries if no reply received from GW/controller. - */ - -#ifndef MY_REGISTRATION_RETRIES -#define MY_REGISTRATION_RETRIES (3u) -#endif - -/** -* @def MY_REGISTRATION_DEFAULT -* @brief Node registration default - this applies if no registration response is received from - * controller. -*/ -#define MY_REGISTRATION_DEFAULT (true) - -/** - * @def MY_REGISTRATION_CONTROLLER - * @brief If defined, node registration request has to be handled by controller - */ -//#define MY_REGISTRATION_CONTROLLER -/** @}*/ // End of RegistrationSettingGrpPub group - -/** - * @defgroup CoreSettingGrpPub Core - * @ingroup MyConfigGrp - * @brief These options control the library core configurations. - * @{ - */ -/** - * @def MY_CORE_ONLY - * @brief Define this if you want to use core functions without loading the framework. - */ -//#define MY_CORE_ONLY - -/** - * @def MY_CORE_COMPATIBILITY_CHECK - * @brief If defined, library compatibility is checked during node registration. - * Incompatible libraries are unable to send sensor data. - */ -#define MY_CORE_COMPATIBILITY_CHECK -/** @}*/ // End of CoreSettingGrpPub group - -/** - * @defgroup SleepSettingGrpPub Sleep - * @ingroup MyConfigGrp - * @brief These options control sleep configurations. - * @{ - */ -/** - * @def MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS - * @brief Timeout (in ms) to re-establish link if node is send to sleep and transport is not ready. - */ -#ifndef MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS -#define MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS (10*1000ul) -#endif - -/** - * @def MY_SMART_SLEEP_WAIT_DURATION_MS - * @brief The wait period (in ms) before going to sleep when using smartSleep-functions. - * - * This period has to be long enough for controller to be able to send out - * potential buffered messages. - */ -#ifndef MY_SMART_SLEEP_WAIT_DURATION_MS -#define MY_SMART_SLEEP_WAIT_DURATION_MS (500ul) -#endif -/** @}*/ // End of SleepSettingGrpPub group - -/** - * @defgroup OTASettingGrpPub Over The Air firmware - * @ingroup MyConfigGrp - * @brief These options control OTA firmware configurations. - * @{ - */ - -/** - * @def MY_OTA_FIRMWARE_FEATURE - * @brief Define this in sketch to allow safe over-the-air firmware updates. - * - * This feature requires external flash and the DualOptiBoot boot-loader. - * @note You can still have OTA FW updates without external flash but it - * requires the MYSBootloader and you must not define this flag. - */ -//#define MY_OTA_FIRMWARE_FEATURE - -/** - * @def MY_OTA_FLASH_SS - * @brief Slave select pin for external flash used for OTA. - */ -#ifndef MY_OTA_FLASH_SS -#define MY_OTA_FLASH_SS (8) -#endif - -/** - * @def MY_OTA_FLASH_JDECID - * @brief Flash JDECID used for OTA. Use (0x00) if unknown. - */ -#ifndef MY_OTA_FLASH_JDECID -#define MY_OTA_FLASH_JDECID (0x1F65) -#endif - -/** - * @def MY_DISABLE_REMOTE_RESET - * @brief Disables over-the-air reset of node - */ -//#define MY_DISABLE_REMOTE_RESET -/** @}*/ // End of OTASettingGrpPub group - -/** - * @defgroup GatewaySettingGrpPub Gateway - * @ingroup MyConfigGrp - * @brief These options control gateway specific configurations. - * @{ - */ -/** - * @def MY_GATEWAY_MAX_RECEIVE_LENGTH - * @brief Max buffersize needed for messages coming from controller. - */ -#ifndef MY_GATEWAY_MAX_RECEIVE_LENGTH -#define MY_GATEWAY_MAX_RECEIVE_LENGTH (100u) -#endif - -/** - * @def MY_GATEWAY_MAX_SEND_LENGTH - * @brief Max buffer size when sending messages. - */ -#ifndef MY_GATEWAY_MAX_SEND_LENGTH -#define MY_GATEWAY_MAX_SEND_LENGTH (120u) -#endif - -/** - * @def MY_GATEWAY_MAX_CLIENTS - * @brief Max number of parallel clients (sever mode). - */ -#ifndef MY_GATEWAY_MAX_CLIENTS -#define MY_GATEWAY_MAX_CLIENTS (1u) -#endif - -/** - * @def MY_INCLUSION_MODE_FEATURE - * @brief Define this to enable the inclusion mode feature. - */ -//#define MY_INCLUSION_MODE_FEATURE - -/** - * @def MY_INCLUSION_BUTTON_FEATURE - * @brief Enables inclusion-mode button feature on the gateway device. - * - * With this defined, you can put the GW in inclusion mode by pressing a button attached to the GW. - */ -//#define MY_INCLUSION_BUTTON_FEATURE - -// Disable inclusion mode button if inclusion mode feature is not enabled -#ifndef MY_INCLUSION_MODE_FEATURE -#undef MY_INCLUSION_BUTTON_FEATURE -#endif - -/** - * @def MY_INCLUSION_LED_PIN - * @brief Enables an inclusion mode LED indicator on the gateway device. - * - * With this defined, inclusion mode status (on or off) is indicated by the LED. - * This feature obeys @ref MY_WITH_LEDS_BLINKING_INVERSE - */ -//#define MY_INCLUSION_LED_PIN (7) - -/** - * @def MY_INCLUSION_MODE_BUTTON_PIN - * @brief The default input pin used for the inclusion mode button. - */ -#ifndef MY_INCLUSION_MODE_BUTTON_PIN -#if defined(ARDUINO_ARCH_ESP8266) -#define MY_INCLUSION_MODE_BUTTON_PIN (5) -#else -#define MY_INCLUSION_MODE_BUTTON_PIN (3) -#endif -#endif - -/** - * @def MY_INCLUSION_MODE_DURATION - * @brief Number of seconds inclusion mode should be enabled. - */ -#ifndef MY_INCLUSION_MODE_DURATION -#define MY_INCLUSION_MODE_DURATION (60) -#endif - -/** - * @def MY_INCLUSION_BUTTON_EXTERNAL_PULLUP - * @brief Define this to change the default state for @ref MY_INCLUSION_BUTTON_PRESSED. - */ -/** - * @def MY_INCLUSION_BUTTON_PRESSED - * @brief The logical level indicating a pressed inclusion mode button. - * - * If @ref MY_INCLUSION_BUTTON_EXTERNAL_PULLUP is defined, this defaults to HIGH. - */ -#if defined(MY_INCLUSION_BUTTON_EXTERNAL_PULLUP) -#define MY_INCLUSION_BUTTON_PRESSED (HIGH) -#else -#define MY_INCLUSION_BUTTON_PRESSED (LOW) -#endif - - -/************************************** -* Ethernet Gateway Transport Defaults -***************************************/ -/** - * @def MY_GATEWAY_W5100 - * @brief Define this for Ethernet GW based on the W5100 module. - * @def MY_GATEWAY_ENC28J60 - * @brief Define this for Ethernet GW based on the ENC28J60 module. - * @def MY_GATEWAY_ESP8266 - * @brief Define this for Ethernet GW based on the ESP8266. - * @def MY_GATEWAY_ESP32 - * @brief Define this for Ethernet GW based on the ESP32. - * @def MY_GATEWAY_LINUX - * @brief Define this for Ethernet GW based on Linux. - * @def MY_GATEWAY_TINYGSM - * @brief Define this for Ethernet GW based on GSM modems supported by TinyGSM library. - * @def MY_GATEWAY_MQTT_CLIENT - * @brief Define this for MQTT client GW. - * @def MY_GATEWAY_SERIAL - * @brief Define this for Serial GW. - */ -// The gateway options available -//#define MY_GATEWAY_W5100 -//#define MY_GATEWAY_ENC28J60 -//#define MY_GATEWAY_ESP8266 -//#define MY_GATEWAY_ESP32 -//#define MY_GATEWAY_LINUX -//#define MY_GATEWAY_TINYGSM -//#define MY_GATEWAY_MQTT_CLIENT -//#define MY_GATEWAY_SERIAL - - -/** -* @def MY_DEBUG_VERBOSE_GATEWAY -* @brief Define this for verbose debug prints related to the gateway transport. -*/ -//#define MY_DEBUG_VERBOSE_GATEWAY - -/** -* @def MY_WIFI_SSID -* @brief SSID of your WiFi network -*/ -//#define MY_WIFI_SSID "MySSID" - -/** -* @def MY_WIFI_BSSID -* @brief BSSID of your WiFi network -*/ -#ifndef MY_WIFI_BSSID -#define MY_WIFI_BSSID NULL -#endif - -/** -* @def MY_WIFI_PASSWORD -* @brief Password of your WiFi network -*/ -//#define MY_WIFI_PASSWORD "MyVerySecretPassword" - -/** -* @def MY_HOSTNAME -* @brief Hostname of your device -*/ -#ifndef MY_HOSTNAME -#define MY_HOSTNAME "MYSENSORS_DEVICE" -#endif - -/** - * @def MY_PORT - * @brief The Ethernet TCP/UDP port to open on controller or gateway. - */ -#ifndef MY_PORT -#ifdef MY_GATEWAY_MQTT_CLIENT -#define MY_PORT 1883 -#else -#define MY_PORT 5003 -#endif -#endif - -/** - * @def MY_MQTT_CLIENT_PUBLISH_RETAIN - * @brief Enables MQTT client to set the retain flag when publishing specific messages. - */ -//#define MY_MQTT_CLIENT_PUBLISH_RETAIN - -/** - * @def MY_MQTT_PASSWORD - * @brief Used for authenticated MQTT connections. - * - * Set if your MQTT broker requires username/password. - * Example: @code #define MY_MQTT_PASSWORD "secretpassword" @endcode - * @see MY_MQTT_USER - */ -//#define MY_MQTT_PASSWORD "secretpassword" - -/** - * @def MY_MQTT_USER - * @brief Used for authenticated MQTT connections. - * - * Set if your MQTT broker requires username/password. - * Example: @code #define MY_MQTT_USER "username" @endcode - * @see MY_MQTT_PASSWORD - */ -//#define MY_MQTT_USER "username" - -/** - * @def MY_MQTT_CLIENT_ID - * @brief Set client ID for MQTT connections - * - * This define is mandatory for all MQTT client gateways. - * Example: @code #define MY_MQTT_CLIENT_ID "mysensors-1" @endcode - */ -//#define MY_MQTT_CLIENT_ID "mysensors-1" - -/** - * @def MY_MQTT_PUBLISH_TOPIC_PREFIX - * @brief Set prefix for MQTT topic to publish to. - * - * This define is mandatory for all MQTT client gateways. - * Example: @code #define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out" @endcode - */ -//#define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out" - -/** - * @def MY_MQTT_SUBSCRIBE_TOPIC_PREFIX - * @brief Set prefix for MQTT topic to subscribe to. - * - * This define is mandatory for all MQTT client gateways. - * Example: @code #define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in" @endcode - */ -//#define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in" - -/** - * @def MY_IP_ADDRESS - * @brief Static ip address of gateway. If not defined, DHCP will be used. - * - * Example: @code #define MY_IP_ADDRESS 192,168,178,66 @endcode - */ -//#define MY_IP_ADDRESS 192,168,178,66 - -/** - * @def MY_IP_GATEWAY_ADDRESS - * @brief IP address of your broadband router/gateway, if not using DHCP. - * - * Example: @code #define MY_IP_GATEWAY_ADDRESS 192,168,1,1 @endcode - */ -//#define MY_IP_GATEWAY_ADDRESS 192,168,1,1 - -/** - * @def MY_IP_SUBNET_ADDRESS - * @brief Subnet address of your local network, if not using DHCP. - * - * Example: @code #define MY_IP_SUBNET_ADDRESS 255,255,255,0 @endcode - */ -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -/** - * @def MY_USE_UDP - * @brief Enables UDP mode for Ethernet gateway. - * @note This is not supported on ENC28J60 and Linux based GWs. - */ -//#define MY_USE_UDP - -/** - * @def MY_IP_RENEWAL_INTERVAL_MS - * @brief DHCP, default renewal setting in milliseconds. - */ -#ifndef MY_IP_RENEWAL_INTERVAL_MS -#define MY_IP_RENEWAL_INTERVAL_MS (60*1000ul) -#endif - -/** - * @def MY_MAC_ADDRESS - * @brief Ethernet MAC address. - * @note This needs to be unique on the network. - */ -#ifndef MY_MAC_ADDRESS -#define MY_MAC_ADDRESS 0xDE,0xAD,0xBE,0xEF,0xFE,0xED -#endif - -/** - * @def MY_CONTROLLER_IP_ADDRESS - * @brief If this is defined, gateway will act as a client trying to contact controller on - * @ref MY_PORT using this IP address. - * - * Example: @code #define MY_CONTROLLER_IP_ADDRESS 192,168,178,254 @endcode - * - * If left un-defined, gateway acts as server allowing incoming connections. - * @see MY_CONTROLLER_URL_ADDRESS - */ -//#define MY_CONTROLLER_IP_ADDRESS 192,168,178,254 - -/** - * @def MY_CONTROLLER_URL_ADDRESS - * @brief If this is defined, gateway will act as a client (ethernet or MQTT) trying to - * contact controller on the given URL. - * - * If left un-defined, gateway acts as server allowing incoming connections. - * Example: @code #define MY_CONTROLLER_URL_ADDRESS "test.mosquitto.org" @endcode - * @see MY_CONTROLLER_IP_ADDRESS - * @see MY_GATEWAY_MQTT_CLIENT - */ -//#define MY_CONTROLLER_URL_ADDRESS "test.mosquitto.org" - -/** @}*/ // End of GatewaySettingGrpPub group - -/** - * @defgroup GSMSettingGrpPub GSM - * @ingroup MyConfigGrp - * @brief These options control GSM specific configurations. - * @{ - */ -/** - * @def MY_GSM_APN - * @brief APN from your cell carrier / mobile provider. Example: 4g.tele2.se - */ -//#define MY_GSM_APN -/** -* @def MY_GSM_BAUDRATE -* @brief Baudrate for your GSM modem. If left undefined, TinyGSM will try to auto detect the correct rate -*/ -//#define MY_GSM_BAUDRATE (9600u) -/** -* @def MY_GSM_PIN -* @brief PIN code for your SIM card, if PIN lock is active. -*/ -//#define MY_GSM_PIN -/** -* @def MY_GSM_PSW -* @brief If using a GSM modem, this is the password supplied by your cell carrier / mobile provider. If using ESP8266 as a WiFi modem, this is your WiFi network password -*/ -//#define MY_GSM_PSW -/** -* @def MY_GSM_RX -* @brief If defined, uses softSerial using defined pins (must also define MY_GSM_TX) -*/ -//#define MY_GSM_RX -/** -* @def MY_GSM_SSID -* @brief If using ESP8266 as WiFi modem, this is your network SSID -*/ -//#define MY_GSM_SSID -/** -* @def MY_GSM_TX -* @brief If defined, uses softSerial using defined pins (must also define MY_GSM_RX) -*/ -//#define MY_GSM_TX -/** -* @def MY_GSM_USR -* @brief Supplied by your cell carrier / mobile operator. If not required, leave undefined. -*/ -//#define MY_GSM_USR - -/** @}*/ // End of GSMSettingGrpPub group - -/** - * @defgroup LEDSettingGrpPub LED - * @ingroup MyConfigGrp - * @brief These options control LED specific configurations. - * @{ - */ -/** - * @def MY_DEFAULT_ERR_LED_PIN - * @brief Define this with a value that correspond to your placement of the error indication LED. - * - * @note This is optional. - * @note On some platforms (for example sensebender GW) the hardware definitions can enable the LED - * by default. That default can be overridden by defining this flag. - */ -//#define MY_DEFAULT_ERR_LED_PIN (6) - -/** - * @def MY_DEFAULT_TX_LED_PIN - * @brief Define this with a value that correspond to your placement of the TX indication LED. - * - * @note This is optional. - * @note On some platforms (for example sensebender GW) the hardware definitions can enable the LED - * by default. That default can be overridden by defining this flag. - */ -//#define MY_DEFAULT_TX_LED_PIN (7) - -/** - * @def MY_DEFAULT_RX_LED_PIN - * @brief Define this with a value that correspond to your placement of the RX indication LED. - * - * @note This is optional. - * @note On some platforms (for example sensebender GW) the hardware definitions can enable the LED - * by default. That default can be overridden by defining this flag. - */ -//#define MY_DEFAULT_RX_LED_PIN (8) - -/** - * @def MY_WITH_LEDS_BLINKING_INVERSE - * @brief Define this to inverse the LED blinking. - * - * When defined LEDs are normally turned on and switches off when blinking. - */ -//#define MY_WITH_LEDS_BLINKING_INVERSE - -/** - * @def MY_INDICATION_HANDLER - * @brief Define to use own indication handler. - */ -//#define MY_INDICATION_HANDLER - -/** -* @def MY_DEFAULT_LED_BLINK_PERIOD -* @brief Default LEDs blinking period in milliseconds. -*/ -#ifndef MY_DEFAULT_LED_BLINK_PERIOD -#define MY_DEFAULT_LED_BLINK_PERIOD 300 -#endif -/** @}*/ // End of LEDSettingGrpPub group - -/** - * @defgroup SecuritySettingGrpPub Security - * @ingroup MyConfigGrp - * @brief These options control security related configurations. - * - * Overview over all security related settings and how/where to apply them: - * | Setting | Description | Arduino | Raspberry PI @c configure argument - * |--------------------------|-------------|---------|------------- - * | @ref MY_SECURITY_SIMPLE_PASSWD | Enables security (signing and encryption) without the need for @ref personalization | "#define" in the top of your sketch | Not supported (use the other two "simple" options) - * | @ref MY_SIGNING_SIMPLE_PASSWD | Enables signing without the need for @ref personalization | "#define" in the top of your sketch | @verbatim --my-signing=password --my-security-password= @endverbatim - * | @ref MY_ENCRYPTION_SIMPLE_PASSWD | Enables encryption without the need for @ref personalization | "#define" in the top of your sketch | @verbatim --my-security-password= @endverbatim and encryption enabled on the chosen transport - * | @ref MY_DEBUG_VERBOSE_SIGNING | Enables verbose signing debugging | "#define" in the top of your sketch | @verbatim --my-signing-debug @endverbatim - * | @ref MY_SIGNING_ATSHA204 | Enables support to sign messages backed by ATSHA204A hardware | "#define" in the top of your sketch | Not supported - * | @ref MY_SIGNING_SOFT | Enables support to sign messages backed by software | "#define" in the top of your sketch | @verbatim --my-signing=software @endverbatim - * | @ref MY_SIGNING_REQUEST_SIGNATURES | Enables node/gw to require signed messages | "#define" in the top of your sketch | @verbatim --my-signing-request-signatures @endverbatim - * | @ref MY_SIGNING_WEAK_SECURITY | Weakens signing security, useful for testing before deploying signing "globally" | "#define" in the top of your sketch | @verbatim --my-signing-weak_security @endverbatim - * | @ref MY_VERIFICATION_TIMEOUT_MS | Change default signing timeout | "#define" in the top of your sketch | @verbatim --my-signing-verification-timeout-ms= @endverbatim - * | @ref MY_SIGNING_NODE_WHITELISTING | Defines a whitelist of trusted nodes | "#define" in the top of your sketch | @verbatim --my-signing-whitelist="" @endverbatim - * | @ref MY_SIGNING_ATSHA204_PIN | Change default ATSHA204A communication pin | "#define" in the top of your sketch | Not supported - * | @ref MY_SIGNING_SOFT_RANDOMSEED_PIN | Change default software RNG seed pin | "#define" in the top of your sketch | Not supported - * | @ref MY_RF24_ENABLE_ENCRYPTION | Enables encryption on RF24 radios | "#define" in the top of your sketch | @verbatim --my-rf24-encryption-enabled @endverbatim - * | @ref MY_RFM69_ENABLE_ENCRYPTION | Enables encryption on %RFM69 radios | "#define" in the top of your sketch | @verbatim --my-rfm69-encryption-enabled @endverbatim - * | @ref MY_RFM95_ENABLE_ENCRYPTION | Enables encryption on %RFM95 radios | "#define" in the top of your sketch | @verbatim --my-rfm95-encryption-enabled @endverbatim - * | @ref MY_NRF5_ESB_ENABLE_ENCRYPTION | Enables encryption on nRF5 radios | "#define" in the top of your sketch | Not supported - * | @ref MY_NODE_LOCK_FEATURE | Enables the node locking feature | "#define" in the top of your sketch | Not supported - * | @ref MY_NODE_UNLOCK_PIN | Change default unlock pin | "#define" in the top of your sketch | Not supported - * | @ref MY_NODE_LOCK_COUNTER_MAX | Change default "malicious activity" counter max value | "#define" in the top of your sketch | Not supported - * - * @{ - */ -/** - * @def MY_SECURITY_SIMPLE_PASSWD - * @brief Enables SW backed signing functionality and encryption functionality in library and uses - * provided password as key. - * - * Example: @code #define MY_SECURITY_SIMPLE_PASSWD "MyInsecurePassword" @endcode - * - * For details on the effects, see the references. - * @see MY_SIGNING_SIMPLE_PASSWD, MY_ENCRYPTION_SIMPLE_PASSWD - */ -//#define MY_SECURITY_SIMPLE_PASSWD "MyInsecurePassword" -#if defined(MY_SECURITY_SIMPLE_PASSWD) -#define MY_SIGNING_SIMPLE_PASSWD MY_SECURITY_SIMPLE_PASSWD -#define MY_ENCRYPTION_SIMPLE_PASSWD MY_SECURITY_SIMPLE_PASSWD -#endif - -/** - * @defgroup SigningSettingGrpPub Signing - * @ingroup SecuritySettingGrpPub - * @brief These options control signing related configurations. - * - * @see MySigninggrpPub - * @{ - */ -/** -* @def MY_DEBUG_VERBOSE_SIGNING -* @brief Define this for verbose debug prints related to signing. -*/ -//#define MY_DEBUG_VERBOSE_SIGNING - -/** - * @def MY_SIGNING_SIMPLE_PASSWD - * @brief Enables SW backed signing functionality in library and uses provided password as key. - * - * This flag is automatically set if @ref MY_SECURITY_SIMPLE_PASSWD is used. - * - * This flag will enable signing and signature requests. It has to be identical on ALL nodes in the - * network. - * - * Whitelisting is supported and serial will be the first 8 characters of the password, the ninth - * character will be the node ID (to make each node have a unique serial). - * - * As with the regular signing modes, whitelisting is only activated if a whitelist is specified in - * the sketch. - * - * No @ref personalization is required for this mode. - * - * It is allowed to set @ref MY_SIGNING_WEAK_SECURITY for deployment purposes in this mode as it is - * with the regular software and ATSHA204A based modes. - * - * If the provided password is shorter than the size of the HMAC key, it will be null-padded - * to accommodate the key size in question. A 32 character password is the maximum length. Any - * password longer than that will be truncated. - * - * Example: @code #define MY_SIGNING_SIMPLE_PASSWD "MyInsecurePassword" @endcode - * - * @see MY_SECURITY_SIMPLE_PASSWD - * - */ -//#define MY_SIGNING_SIMPLE_PASSWD "MyInsecurePassword" -#if defined(MY_SIGNING_SIMPLE_PASSWD) -#define MY_SIGNING_SOFT -#define MY_SIGNING_REQUEST_SIGNATURES -#endif - -/** - * @def MY_SIGNING_ATSHA204 - * @brief Enables HW backed signing functionality in library. - */ -//#define MY_SIGNING_ATSHA204 - -/** - * @def MY_SIGNING_SOFT - * @brief Enables SW backed signing functionality in library. - */ -//#define MY_SIGNING_SOFT - -/** - * @def MY_SIGNING_REQUEST_SIGNATURES - * @brief Enable this to inform gateway to sign all messages sent to this node. - * - * If used for a gateway, gateway will by default require signatures from ALL nodes. This behavior - * can be disabled by weakening security. - * @see MY_SIGNING_WEAK_SECURITY - */ -//#define MY_SIGNING_REQUEST_SIGNATURES - -/** - * @def MY_SIGNING_WEAK_SECURITY - * @brief Enable this to permit downgrade of security preferences and relaxed gateway signing - * requirements. - * - * Use this for evaluating security. It allows for gradual introduction of signing requirements in - * a network. Nodes that present themselves as not requiring signing or whitelisting will be - * cleared of this requirement at the receiving end. A gateway which require signatures will only do - * so from nodes that in turn require signatures. - * - * When not set, any node that has presented themselves as a node that require signatures or - * whitelisting, will be permanently remembered as doing so at the receiver until EEPROM is cleared - * or the receiver is reconfigured with this flag set or has signing disabled alltogether. - * - * @warning This flag when set will weaken security significantly - */ -//#define MY_SIGNING_WEAK_SECURITY - -/** - * @def MY_VERIFICATION_TIMEOUT_MS - * @brief Define a suitable timeout for a signature verification session - * - * Consider the turnaround from a nonce being generated to a signed message being received - * which might vary, especially in networks with many hops. - * - * Shorter time gives less time for an attacker to figure a way to hijack the nonce and attempt to - * brute force attack the node. Longer time permits more network hops and node or GW processing - * time. 5s ought to be enough for anyone. - */ -#ifndef MY_VERIFICATION_TIMEOUT_MS -#define MY_VERIFICATION_TIMEOUT_MS (5*1000ul) -#endif - -/** - * @def MY_SIGNING_NODE_WHITELISTING - * @brief Define to turn on whitelisting - * - * When defined, a verifying node will look up the sender in the whitelist and salt the received - * signature with that information before validating the result. It will also inform GW (or other - * node) through the signing presentation message about this requirement. - * - * The signing node will check the presentaiton lists to determine if the recipient require - * whitelisting and salt the signature with it's unique signature and nodeId before transmitting - * the signed message. - * - * It is legal to only have one node with a whitelist for this reason but it is not required. - * - * Example: @code #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} @endcode - */ -//#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} - -/** - * @def MY_SIGNING_ATSHA204_PIN - * @brief Atsha204a default pin setting. Set it to match the pin the device is attached to. - */ -#ifndef MY_SIGNING_ATSHA204_PIN -#define MY_SIGNING_ATSHA204_PIN (17) -#endif - -/** - * @def MY_SIGNING_SOFT_RANDOMSEED_PIN - * @brief Pin used for random seed generation in soft signing - * @note Do not connect anything to this when soft signing is enabled, or the seed will be - * predictable. - */ -#ifndef MY_SIGNING_SOFT_RANDOMSEED_PIN -#define MY_SIGNING_SOFT_RANDOMSEED_PIN (7) -#endif - -/** - * @def MY_LOCK_DEVICE - * @brief Enable read back protection - * - * Enable read back protection feature. Currently only supported by NRF51+NRF52. - * Use this flag to protect signing and encryption keys stored in the MCU. - * - * Set this flag, when you use softsigning in MySensors. Don't set this - * in SecurityPersonalizer. - * - * @warning YOU CAN BRICK YOUR DEVICE!!! - * Don't set this flag without having an boot loader, OTA firmware update and - * an Gateway connection. To reset an device, you can try >> - * openocd -f interface/cmsis-dap.cfg -f target/nrf52.cfg -c "program dap apreg 1 0x04 0x01" - */ -//#define MY_LOCK_DEVICE - -/** - * @def MY_SIGNING_FEATURE - * @ingroup internals - * @brief Helper flag to indicate that some signing feature is enabled, set automatically - */ -#if defined(MY_SIGNING_ATSHA204) || defined(MY_SIGNING_SOFT) -#define MY_SIGNING_FEATURE -#endif -/** @}*/ // End of SigningSettingGrpPub group - -/** - * @defgroup EncryptionSettingGrpPub Encryption - * @ingroup SecuritySettingGrpPub - * @brief These options control encryption related configurations. - * - * Note that encryption is toggled on a per-radio basis. - * @see MY_RF24_ENABLE_ENCRYPTION, MY_RFM69_ENABLE_ENCRYPTION, MY_NRF5_ESB_ENABLE_ENCRYPTION, MY_RFM95_ENABLE_ENCRYPTION - * @{ - */ - -/** - * @def MY_ENCRYPTION_SIMPLE_PASSWD - * @brief Enables encryption on all radio transports that supports it and uses provided password as key. - * - * This flag is automatically set if @ref MY_SECURITY_SIMPLE_PASSWD is used. - * - * This flag will enable encryption. It has to be identical on ALL nodes in the network. - * - * No @ref personalization is required for this mode. - * - * If the provided password is shorter than the size of the %AES key, it will be null-padded - * to accommodate the key size in question. A 16 character password is the maximum length. Any - * password longer than that will be truncated. - * - * Example: @code #define MY_ENCRYPTION_SIMPLE_PASSWD "MyInsecurePassword" @endcode - * - * @see MY_SECURITY_SIMPLE_PASSWD - */ -//#define MY_ENCRYPTION_SIMPLE_PASSWD "MyInsecurePassword" -#if defined(MY_ENCRYPTION_SIMPLE_PASSWD) -#ifndef MY_RF24_ENABLE_ENCRYPTION -#define MY_RF24_ENABLE_ENCRYPTION -#endif -#ifndef MY_RFM69_ENABLE_ENCRYPTION -#define MY_RFM69_ENABLE_ENCRYPTION -#endif -#ifndef MY_NRF5_ESB_ENABLE_ENCRYPTION -#define MY_NRF5_ESB_ENABLE_ENCRYPTION -#endif -#ifndef MY_RFM95_ENABLE_ENCRYPTION -#define MY_RFM95_ENABLE_ENCRYPTION -#endif -#endif - -/** - * @def MY_ENCRYPTION_FEATURE - * @ingroup internals - * @brief Helper flag to indicate that some encryption feature is enabled, set automatically - * @see MY_RF24_ENABLE_ENCRYPTION, MY_RFM69_ENABLE_ENCRYPTION, MY_NRF5_ESB_ENABLE_ENCRYPTION, MY_RFM95_ENABLE_ENCRYPTION - */ -#if defined(MY_RF24_ENABLE_ENCRYPTION) || defined(MY_RFM69_ENABLE_ENCRYPTION) || defined(MY_NRF5_ESB_ENABLE_ENCRYPTION) || defined(MY_RFM95_ENABLE_ENCRYPTION) -#define MY_ENCRYPTION_FEATURE -#endif -/** @}*/ // End of EncryptionSettingGrpPub group - -/** - * @defgroup MyLockgrppub Node locking - * @ingroup MyConfig - * @brief These options control node lock related configurations. - * - * This feature locks a node that suspect itself for being under some form of attack. - * - * This is achieved by having a counter stored in EEPROM which decrements when suspicious activity - * is detected. - * - * If the counter reaches 0, the node will not work anymore and will transmit a @ref I_LOCKED - * message to the gateway/controller with 30 minute intervals. Payload is a string with a reason for - * the locking. - * - * The string is abbreviated to accommodate a signature. The following abbreviations exist at the - * moment: - * - LDB (Locked During Boot) - * - TMNR (Too Many Nonce Requests) - * - TMFV (Too Many Failed Verifications) - * - * Typically, the counter only decrements when suspicious activity happens in a row. - * It is reset if legit traffic is present. - * - * Examples of malicious activity are: - * - Repeatedly incorrectly checksummed OTA firmware - * - Repeated requests for signing nonces without properly signed messages arriving - * - Repeatedly failed signature verifications - * - * If counter reaches zero, node locks down and EEPROM has to be erased/reset to reactivate node. - * Node can also be unlocked by grounding a pin. - * @see MY_NODE_UNLOCK_PIN - * - * The size of the counter can be adjusted using @ref MY_NODE_LOCK_COUNTER_MAX. - * @{ - */ -/** - * @def MY_NODE_LOCK_FEATURE - * @brief Enable this to activate intrusion prevention mechanisms on the node. - */ -//#define MY_NODE_LOCK_FEATURE - -/** - * @def MY_NODE_UNLOCK_PIN - * @brief By grounding this pin during reset of a locked node, the node will unlock. - * - * If using a secure bootloader, grounding the pin is the only option to reactivate the node. - * If using stock Android bootloader or a DualOptiBoot it is also possible to download a sketch - * using serial protocol to erase EEPROM to unlock the node. - */ -#ifndef MY_NODE_UNLOCK_PIN -#define MY_NODE_UNLOCK_PIN (14) -#endif - -/** - * @def MY_NODE_LOCK_COUNTER_MAX - * @brief Maximum accepted occurrences of suspected malicious activity in a node. - * - * Counter decrements on reoccurring incidents but resets if legitimate behaviour is identified. - */ -#ifndef MY_NODE_LOCK_COUNTER_MAX -#define MY_NODE_LOCK_COUNTER_MAX (5) -#endif -/** @}*/ // Node lock group -/** @}*/ // End of SecuritySettingGrpPub group - -/** - * @defgroup PlatformSettingGrpPub Platform specifics - * @ingroup MyConfigGrp - * @brief These options control platform specific configurations. - * @{ - */ -/** - * @defgroup ESP8266SettingGrpPub ESP8266 - * @ingroup PlatformSettingGrpPub - * @brief These options control ESP8266 specific configurations. - * @{ - */ -/** - * @def MY_ESP8266_SERIAL_MODE - * @brief ESP8266 serial modes - * - * - SERIAL_FULL: Default mode. - * - SERIAL_TX_ONLY: allows to use RX (GPIO3) as a general purpose input/output. - * - SERIAL_RX_ONLY: allows to use TX (GPIO1) as a general purpose input/output. - */ -#ifndef MY_ESP8266_SERIAL_MODE -#define MY_ESP8266_SERIAL_MODE SERIAL_FULL -#endif -/** @}*/ // End of ESP8266SettingGrpPub group - -/** -* @defgroup ESP32SettingGrpPub ESP32 -* @ingroup PlatformSettingGrpPub -* @brief These options control ESP32 specific configurations. -* @{ -*/ - -// -// no ESP32 settings -// - -/** @}*/ // End of ESP32SettingGrpPub group - -/** - * @defgroup LinuxSettingGrpPub Linux - * @ingroup PlatformSettingGrpPub - * @brief These options control Linux specific configurations. - * @{ - */ - -/** - * @def MY_LINUX_SERIAL_PORT - * @brief Serial device port - */ -//#define MY_LINUX_SERIAL_PORT "/dev/ttyUSB0" - -/** - * @def MY_LINUX_SERIAL_PTY - * @brief deprecated option - */ -#ifdef MY_LINUX_SERIAL_PTY -#warning MY_LINUX_SERIAL_PTY is deprecated, please use MY_LINUX_SERIAL_PORT -#define MY_LINUX_SERIAL_PORT MY_LINUX_SERIAL_PTY -#endif - -/** - * @def MY_LINUX_IS_SERIAL_PTY - * @brief deprecated option - */ -#ifdef MY_LINUX_IS_SERIAL_PTY -#warning MY_LINUX_IS_SERIAL_PTY is deprecated, please use MY_LINUX_SERIAL_IS_PTY -#define MY_LINUX_SERIAL_IS_PTY -#endif - -/** - * @def MY_LINUX_SERIAL_IS_PTY - * @brief Set serial as a pseudo terminal. - * - * Enable this if you need to connect to a controller running on the same device. - * You also need to define MY_LINUX_SERIAL_PORT with the symlink name for the PTY device. - */ -//#define MY_LINUX_SERIAL_IS_PTY - -/** - * @def MY_LINUX_SERIAL_GROUPNAME - * @brief Grant access to the specified system group for the serial device. - */ -//#define MY_LINUX_SERIAL_GROUPNAME "tty" - -/** - * @def MY_LINUX_CONFIG_FILE - * @brief Sets the filepath for the gateway config file. - * - * @note For now the configuration file is only used to store the emulated eeprom state. - */ -#ifndef MY_LINUX_CONFIG_FILE -#define MY_LINUX_CONFIG_FILE "/etc/mysensors.conf" -#endif -/** @}*/ // End of LinuxSettingGrpPub group -/** @}*/ // End of PlatformSettingGrpPub group - -/* -* "Helper" definitions -*/ - -/* - * Detect node type - * MY_GATEWAY_FEATURE is set for gateway sketches. - * MY_IS_GATEWAY is true when @ref MY_GATEWAY_FEATURE is set. - * MY_NODE_TYPE contain a string describing the class of sketch/node (gateway/repeater/node). - */ -#if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) || defined(MY_GATEWAY_ENC28J60) || defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)|| defined(MY_GATEWAY_LINUX) || defined(MY_GATEWAY_MQTT_CLIENT) || defined(MY_GATEWAY_TINYGSM) -#define MY_GATEWAY_FEATURE -#define MY_IS_GATEWAY (true) -#define MY_NODE_TYPE "GW" -#elif defined(MY_REPEATER_FEATURE) -#define MY_IS_GATEWAY (false) -#define MY_NODE_TYPE "REPEATER" -#elif defined(DOXYGEN) -#define MY_IS_GATEWAY //!< true when configuration indicate a gateway device, @todo Mark these internals -#define MY_NODE_TYPE //!< "GW" for gateways, REPEATER" for repeaters, "NODE" for nodes, @todo Mark these internals -#else -#define MY_IS_GATEWAY (false) -#define MY_NODE_TYPE "NODE" -#endif - -// DEBUG -#if defined(MY_DISABLED_SERIAL) && !defined(MY_DEBUG_OTA) -#undef MY_DEBUG -#endif -#if defined(MY_DEBUG) -// standard debug output -#define MY_DEBUG_VERBOSE_CORE //!< MY_DEBUG_VERBOSE_CORE -#define MY_DEBUG_VERBOSE_TRANSPORT //!< MY_DEBUG_VERBOSE_TRANSPORT -#define MY_DEBUG_VERBOSE_GATEWAY //!< MY_DEBUG_VERBOSE_GATEWAY -#define MY_DEBUG_VERBOSE_OTA_UPDATE //!< MY_DEBUG_VERBOSE_OTA_UPDATE -#endif - -#if defined(MY_DEBUG) || defined(MY_DEBUG_VERBOSE_CORE) || defined(MY_DEBUG_VERBOSE_TRANSPORT) || defined(MY_DEBUG_VERBOSE_GATEWAY) || defined(MY_DEBUG_VERBOSE_SIGNING) || defined(MY_DEBUG_VERBOSE_OTA_UPDATE) || defined(MY_DEBUG_VERBOSE_RF24) || defined(MY_DEBUG_VERBOSE_NRF5_ESB) || defined(MY_DEBUG_VERBOSE_RFM69) || defined(MY_DEBUG_VERBOSE_RFM95) || defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL) -#define DEBUG_OUTPUT_ENABLED //!< DEBUG_OUTPUT_ENABLED -#ifndef MY_DEBUG_OTA -#define DEBUG_OUTPUT(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug -#else -#ifndef MY_OTA_LOG_SENDER_FEATURE -#define MY_OTA_LOG_SENDER_FEATURE -#endif -#ifndef MY_DEBUG_OTA_DISABLE_ECHO -#define DEBUG_OUTPUT(x,...) OTALog((MY_DEBUG_OTA), true, x, ##__VA_ARGS__) //!< debug -#else -#define DEBUG_OUTPUT(x,...) OTALog((MY_DEBUG_OTA), false, x, ##__VA_ARGS__) //!< debug -#endif -// disable radio related debugging messages -#undef MY_DEBUG_VERBOSE_RF24 -#undef MY_DEBUG_VERBOSE_NRF5_ESB -#undef MY_DEBUG_VERBOSE_RFM69 -#undef MY_DEBUG_VERBOSE_RFM69_REGISTERS -#undef MY_DEBUG_VERBOSE_RFM95 -#endif -#else -#define DEBUG_OUTPUT(x,...) //!< debug NULL -#endif - -// temp. workaround for nRF5 verifier: redirect RF24 to NRF_ESB -#if defined(ARDUINO_ARCH_NRF5) && (defined(MY_RADIO_RF24) ) -#undef MY_RADIO_RF24 -#define MY_RADIO_NRF5_ESB -#endif - -// Enable sensor network "feature" if one of the transport types was enabled -#if defined(MY_RADIO_RF24) || defined(MY_RADIO_NRF5_ESB) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) || defined(MY_RS485) -#define MY_SENSOR_NETWORK -#endif - -// LEDS -#if !defined(MY_DEFAULT_ERR_LED_PIN) && defined(MY_HW_ERR_LED_PIN) -#define MY_DEFAULT_ERR_LED_PIN MY_HW_ERR_LED_PIN -#endif - -#if !defined(MY_DEFAULT_TX_LED_PIN) && defined(MY_HW_TX_LED_PIN) -#define MY_DEFAULT_TX_LED_PIN MY_HW_TX_LED_PIN -#endif - -#if !defined(MY_DEFAULT_RX_LED_PIN) && defined(MY_HW_TX_LED_PIN) -#define MY_DEFAULT_RX_LED_PIN MY_HW_TX_LED_PIN -#endif - -#endif // MyConfig_h - -// Doxygen specific constructs, not included when built normally -// This is used to enable disabled macros/definitions to be included in the documentation as well. -#if DOXYGEN -/** - * @def ARDUINO_ARCH_SAMD - * @brief Automatically set when building for SAMD targets - */ -#define ARDUINO_ARCH_SAMD - -/** - * @def ARDUINO_ARCH_NRF5 - * @brief Automatically set when building for nRF5 targets - */ -#define ARDUINO_ARCH_NRF5 - -/** - * @def ARDUINO_ARCH_ESP8266 - * @brief Automatically set when building for ESP8266 targets - */ -#define ARDUINO_ARCH_ESP8266 - -/** - * @def ARDUINO_ARCH_ESP32 - * @brief Automatically set when building for ESP32 targets - */ -#define ARDUINO_ARCH_ESP32 - -/** - * @def ARDUINO_ARCH_AVR - * @brief Automatically set when building for AVR targets - */ -#define ARDUINO_ARCH_AVR - -/** - * @def ARDUINO_ARCH_STM32F1 - * @brief Automatically set when building for STM32F1 targets - */ -#define ARDUINO_ARCH_STM32F1 - -/** - * @def TEENSYDUINO - * @brief Automatically set when building for Teensy targets - */ -#define TEENSYDUINO - -// debug -#define MY_DEBUG -#define MY_DEBUGDEVICE -#define MY_DEBUG_OTA -#define MY_DEBUG_OTA_DISABLE_ECHO -#define MY_SPECIAL_DEBUG -#define MY_DISABLED_SERIAL -#define MY_SPLASH_SCREEN_DISABLED -// linux -#define MY_LINUX_SERIAL_PORT -#define MY_LINUX_SERIAL_IS_PTY -#define MY_LINUX_SERIAL_GROUPNAME -#define MY_LINUX_SERIAL_PTY -#define MY_LINUX_IS_SERIAL_PTY -// inclusion mode -#define MY_INCLUSION_MODE_FEATURE -#define MY_INCLUSION_BUTTON_FEATURE -// OTA logging and debug -#define MY_OTA_LOG_RECEIVER_FEATURE -#define MY_OTA_LOG_SENDER_FEATURE -// transport -#define MY_PARENT_NODE_IS_STATIC -#define MY_REGISTRATION_CONTROLLER -#define MY_TRANSPORT_UPLINK_CHECK_DISABLED -#define MY_TRANSPORT_SANITY_CHECK -#define MY_NODE_LOCK_FEATURE -#define MY_REPEATER_FEATURE -#define MY_PASSIVE_NODE -#define MY_MQTT_CLIENT_PUBLISH_RETAIN -#define MY_MQTT_PASSWORD -#define MY_MQTT_USER -#define MY_MQTT_CLIENT_ID -#define MY_MQTT_PUBLISH_TOPIC_PREFIX -#define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX -#define MY_SIGNAL_REPORT_ENABLED -// general -#define MY_WITH_LEDS_BLINKING_INVERSE -#define MY_INDICATION_HANDLER -#define MY_DISABLE_REMOTE_RESET -#define MY_DISABLE_RAM_ROUTING_TABLE_FEATURE -#define MY_LOCK_DEVICE -// core -#define MY_CORE_ONLY -// GW -#define MY_DEBUG_VERBOSE_GATEWAY -#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP -#define MY_INCLUSION_LED_PIN -#define MY_GATEWAY_W5100 -#define MY_GATEWAY_ENC28J60 -#define MY_GATEWAY_ESP8266 -#define MY_GATEWAY_ESP32 -#define MY_WIFI_SSID -#define MY_WIFI_BSSID -#define MY_WIFI_PASSWORD -#define MY_HOSTNAME -#define MY_GATEWAY_LINUX -#define MY_GATEWAY_TINYGSM -#define MY_GATEWAY_MQTT_CLIENT -#define MY_GATEWAY_SERIAL -#define MY_IP_ADDRESS -#define MY_IP_GATEWAY_ADDRESS -#define MY_IP_SUBNET_ADDRESS -#define MY_USE_UDP -#define MY_CONTROLLER_IP_ADDRESS -#define MY_CONTROLLER_URL_ADDRESS -// TinyGSM -#define MY_GSM_APN -#define MY_GSM_BAUDRATE -#define MY_GSM_PIN -#define MY_GSM_PSW -#define MY_GSM_RX -#define MY_GSM_SSID -#define MY_GSM_TX -#define MY_GSM_USR -// LED -#define MY_DEFAULT_ERR_LED_PIN -#define MY_DEFAULT_TX_LED_PIN -#define MY_DEFAULT_RX_LED_PIN -// signing -#define MY_SECURITY_SIMPLE_PASSWD -#define MY_SIGNING_SIMPLE_PASSWD -#define MY_ENCRYPTION_SIMPLE_PASSWD -#define MY_SIGNING_ATSHA204 -#define MY_SIGNING_SOFT -#define MY_SIGNING_REQUEST_SIGNATURES -#define MY_SIGNING_WEAK_SECURITY -#define MY_SIGNING_NODE_WHITELISTING -#define MY_DEBUG_VERBOSE_SIGNING -#define MY_SIGNING_FEATURE -#define MY_ENCRYPTION_FEATURE -// FOTA update -#define MY_DEBUG_VERBOSE_OTA_UPDATE -#define MY_OTA_USE_I2C_EEPROM -// RS485 -#define MY_RS485 -#define MY_RS485_DE_PIN -#define MY_RS485_DE_INVERSE -#define MY_RS485_HWSERIAL -// RF24 -#define MY_RADIO_RF24 -#define MY_RADIO_NRF24 //deprecated -#define MY_DEBUG_VERBOSE_RF24 -#define MY_RF24_POWER_PIN -#define MY_RF24_IRQ_PIN -#define MY_RF24_ENABLE_ENCRYPTION -#define MY_RX_MESSAGE_BUFFER_FEATURE -#define MY_RX_MESSAGE_BUFFER_SIZE -// NRF5_ESB -#define MY_RADIO_NRF5_ESB -#define MY_NRF5_ESB_ENABLE_ENCRYPTION -#define MY_DEBUG_VERBOSE_NRF5_ESB -#define MY_NRF5_ESB_REVERSE_ACK_RX -#define MY_NRF5_ESB_REVERSE_ACK_TX -// RFM69 -#define MY_RADIO_RFM69 -#define MY_IS_RFM69HW -#define MY_RFM69_NEW_DRIVER -#define MY_RFM69_POWER_PIN -#define MY_RFM69_MODEM_CONFIGURATION -#define MY_RFM69_ENABLE_ENCRYPTION -#define MY_RFM69_ATC_MODE_DISABLED -#define MY_RFM69_MAX_POWER_LEVEL_DBM -#define MY_RFM69_RST_PIN -#define MY_DEBUG_VERBOSE_RFM69 -#define MY_DEBUG_VERBOSE_RFM69_REGISTERS -// RFM95 -#define MY_RADIO_RFM95 -#define MY_DEBUG_VERBOSE_RFM95 -#define MY_RFM95_ENABLE_ENCRYPTION -#define MY_RFM95_ATC_MODE_DISABLED -#define MY_RFM95_RST_PIN -#define MY_RFM95_MODEM_CONFIGRUATION -#define MY_RFM95_POWER_PIN -#define MY_RFM95_TCXO -#define MY_RFM95_MAX_POWER_LEVEL_DBM -// SOFT-SPI -#define MY_SOFTSPI -#endif -/** @}*/ // End of MyConfig group diff --git a/lib/MySensors/MySensors.h b/lib/MySensors/MySensors.h deleted file mode 100644 index db386ba3..00000000 --- a/lib/MySensors/MySensors.h +++ /dev/null @@ -1,456 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** - * @defgroup MySensorsgrp MySensors - * @ingroup publics - * @{ - * @brief The primary public API declaration for the MySensors library - */ - -/** - * @file MySensors.h - * - * @brief API declaration for MySensors - * - * Include this header into your sketch to include the MySensors library and harness the power of - * all those sensors! - */ -#ifndef MySensors_h -#define MySensors_h - -#ifdef __cplusplus -#include -#endif -#include - -#include "MyConfig.h" -#include "core/MyHelperFunctions.cpp" - -#include "core/MySplashScreen.h" -#include "core/MySensorsCore.h" - -// OTA Debug, has to be defined before HAL -#if defined(MY_OTA_LOG_SENDER_FEATURE) || defined(MY_OTA_LOG_RECEIVER_FEATURE) -#include "core/MyOTALogging.h" -#endif - -// HARDWARE -#include "hal/architecture/MyHwHAL.h" -#include "hal/crypto/MyCryptoHAL.h" -#if defined(ARDUINO_ARCH_ESP8266) -#include "hal/architecture/ESP8266/MyHwESP8266.cpp" -#include "hal/crypto/generic/MyCryptoGeneric.cpp" -#elif defined(ARDUINO_ARCH_ESP32) -#include "hal/architecture/ESP32/MyHwESP32.cpp" -#include "hal/crypto/ESP32/MyCryptoESP32.cpp" -#elif defined(ARDUINO_ARCH_AVR) -#include "hal/architecture/AVR/MyHwAVR.cpp" -#include "hal/crypto/AVR/MyCryptoAVR.cpp" -#elif defined(ARDUINO_ARCH_SAMD) -#include "drivers/extEEPROM/extEEPROM.cpp" -#include "hal/architecture/SAMD/MyHwSAMD.cpp" -#include "hal/crypto/generic/MyCryptoGeneric.cpp" -#elif defined(ARDUINO_ARCH_STM32F1) -#include "hal/architecture/STM32F1/MyHwSTM32F1.cpp" -#include "hal/crypto/generic/MyCryptoGeneric.cpp" -#elif defined(ARDUINO_ARCH_NRF5) || defined(ARDUINO_ARCH_NRF52) -#include "hal/architecture/NRF5/MyHwNRF5.cpp" -#include "hal/crypto/generic/MyCryptoGeneric.cpp" -#elif defined(__arm__) && defined(TEENSYDUINO) -#include "hal/architecture/Teensy3/MyHwTeensy3.cpp" -#include "hal/crypto/generic/MyCryptoGeneric.cpp" -#elif defined(__linux__) -#include "hal/architecture/Linux/MyHwLinuxGeneric.cpp" -#include "hal/crypto/generic/MyCryptoGeneric.cpp" -#else -#error Hardware abstraction not defined (unsupported platform) -#endif - -#include "hal/architecture/MyHwHAL.cpp" - -// commonly used macros, sometimes missing in arch definitions -#if !defined(_BV) -#define _BV(x) (1<<(x)) //!< _BV -#endif - -#if !defined(min) && !defined(__linux__) -#define min(a,b) ((a)<(b)?(a):(b)) //!< min -#endif - -#if !defined(max) && !defined(__linux__) -#define max(a,b) ((a)>(b)?(a):(b)) //!< max -#endif - -#if !defined(MIN) -#define MIN min //!< MIN -#endif - -#if !defined(MAX) -#define MAX max //!< MAX -#endif - -// OTA Debug second part, depends on HAL -#if defined(MY_OTA_LOG_SENDER_FEATURE) || defined(MY_OTA_LOG_RECEIVER_FEATURE) -#include "core/MyOTALogging.cpp" -#endif - -#if defined(MY_LEDS_BLINKING_FEATURE) -#error MY_LEDS_BLINKING_FEATURE is now removed from MySensors core,\ -define MY_DEFAULT_ERR_LED_PIN, MY_DEFAULT_TX_LED_PIN or\ -MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs -#endif - -#if defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) -#include "core/MyLeds.cpp" -#else -#include "core/MyLeds.h" -#endif - -#include "core/MyIndication.cpp" - - -// INCLUSION MODE -#if defined(MY_INCLUSION_MODE_FEATURE) -#include "core/MyInclusionMode.cpp" -#endif - - -// SIGNING -#include "core/MySigning.cpp" -#if defined(MY_SIGNING_FEATURE) -// SIGNING COMMON FUNCTIONS -#if defined(MY_SIGNING_ATSHA204) && defined(MY_SIGNING_SOFT) -#error Only one signing engine can be activated -#endif -#if defined(MY_SIGNING_ATSHA204) && defined(__linux__) -#error No support for ATSHA204 on this platform -#endif - -#if defined(MY_SIGNING_ATSHA204) -#include "core/MySigningAtsha204.cpp" -#include "drivers/ATSHA204/ATSHA204.cpp" -#elif defined(MY_SIGNING_SOFT) -#include "core/MySigningAtsha204Soft.cpp" -#endif -#endif - -// FLASH -#if defined(MY_OTA_FIRMWARE_FEATURE) -#ifndef MCUBOOT_PRESENT -#if defined(MY_OTA_USE_I2C_EEPROM) -#include "drivers/I2CEeprom/I2CEeprom.cpp" -#else -#include "drivers/SPIFlash/SPIFlash.cpp" -#endif -#endif -#include "core/MyOTAFirmwareUpdate.cpp" -#endif - -// GATEWAY - TRANSPORT -#if defined(MY_CONTROLLER_IP_ADDRESS) || defined(MY_CONTROLLER_URL_ADDRESS) -#define MY_GATEWAY_CLIENT_MODE //!< gateway client mode -#endif - -#if defined(MY_USE_UDP) && !defined(MY_GATEWAY_CLIENT_MODE) -#error You must specify MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS for UDP -#endif - - - -// Set MQTT defaults if not set - -#if !defined(MY_MQTT_PUBLISH_TOPIC_PREFIX) -#define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out" -#endif - -#if !defined(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) -#define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in" -#endif - -#if !defined(MY_MQTT_CLIENT_ID) -#define MY_MQTT_CLIENT_ID "mysensors-1" -#endif - -#if defined(MY_GATEWAY_MQTT_CLIENT) -#if defined(MY_SENSOR_NETWORK) -// We assume that a gateway having a radio also should act as repeater -#define MY_REPEATER_FEATURE -#endif - -// GATEWAY - COMMON FUNCTIONS -// We support MQTT Client using W5100, ESP8266, GSM modems supported by TinyGSM library and Linux -#if !defined(MY_GATEWAY_CLIENT_MODE) && !defined(MY_GATEWAY_TINYGSM) -#error You must specify MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS -#endif - -#if defined(MY_GATEWAY_TINYGSM) && !defined(MY_GATEWAY_MQTT_CLIENT) -// TinyGSM currently only supports MQTTClient mode. -#error MY_GATEWAY_TINYGSM only works with MY_GATEWAY_MQTT_CLIENT -#endif - -#include "core/MyGatewayTransport.cpp" -#include "core/MyProtocol.cpp" - -#if defined(MY_GATEWAY_TINYGSM) -#include "drivers/TinyGSM/TinyGsmClient.h" -#endif - -#if defined(MY_GATEWAY_LINUX) -#include "hal/architecture/Linux/drivers/core/EthernetClient.h" -#include "hal/architecture/Linux/drivers/core/EthernetServer.h" -#include "hal/architecture/Linux/drivers/core/IPAddress.h" -#endif -#include "drivers/PubSubClient/PubSubClient.cpp" -#include "core/MyGatewayTransportMQTTClient.cpp" -#elif defined(MY_GATEWAY_FEATURE) -// GATEWAY - COMMON FUNCTIONS -#include "core/MyGatewayTransport.cpp" -#include "core/MyProtocol.cpp" - -// GATEWAY - CONFIGURATION -#if defined(MY_SENSOR_NETWORK) -// We assume that a gateway having a radio also should act as repeater -#define MY_REPEATER_FEATURE -#endif - -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -// GATEWAY - ESP8266 / ESP32 -#include "core/MyGatewayTransportEthernet.cpp" -#elif defined(MY_GATEWAY_LINUX) -// GATEWAY - Generic Linux -#if defined(MY_USE_UDP) -#error UDP mode is not available for Linux -#endif -#include "hal/architecture/Linux/drivers/core/EthernetClient.h" -#include "hal/architecture/Linux/drivers/core/EthernetServer.h" -#include "hal/architecture/Linux/drivers/core/IPAddress.h" -#include "core/MyGatewayTransportEthernet.cpp" -#elif defined(MY_GATEWAY_W5100) -// GATEWAY - W5100 -#include "core/MyGatewayTransportEthernet.cpp" -#elif defined(MY_GATEWAY_ENC28J60) -// GATEWAY - ENC28J60 -#if defined(MY_USE_UDP) -#error UDP mode is not available for ENC28J60 -#endif -#include "core/MyGatewayTransportEthernet.cpp" -#elif defined(MY_GATEWAY_SERIAL) -// GATEWAY - SERIAL -#include "core/MyGatewayTransportSerial.cpp" -#endif -#endif - -// TRANSPORT -#ifndef DOXYGEN -// count enabled transports -#if defined(MY_RADIO_RF24) -#define __RF24CNT 1 //!< __RF24CNT -#else -#define __RF24CNT 0 //!< __RF24CNT -#endif -#if defined(MY_RADIO_NRF5_ESB) -#define __NRF5ESBCNT 1 //!< __NRF5ESBCNT -#else -#define __NRF5ESBCNT 0 //!< __NRF5ESBCNT -#endif -#if defined(MY_RADIO_RFM69) -#define __RFM69CNT 1 //!< __RFM69CNT -#else -#define __RFM69CNT 0 //!< __RFM69CNT -#endif -#if defined(MY_RADIO_RFM95) -#define __RFM95CNT 1 //!< __RFM95CNT -#else -#define __RFM95CNT 0 //!< __RFM95CNT -#endif -#if defined(MY_RS485) -#define __RS485CNT 1 //!< __RS485CNT -#else -#define __RS485CNT 0 //!< __RS485CNT -#endif - -#if (__RF24CNT + __NRF5ESBCNT + __RFM69CNT + __RFM95CNT + __RS485CNT > 1) -#error Only one forward link driver can be activated -#endif -#endif //DOXYGEN - -// SANITY CHECK -#if defined(MY_REPEATER_FEATURE) || defined(MY_GATEWAY_FEATURE) -#define MY_TRANSPORT_SANITY_CHECK //!< enable regular transport sanity checks -#endif - -// TRANSPORT INCLUDES -#if defined(MY_RADIO_RF24) || defined(MY_RADIO_NRF5_ESB) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) || defined(MY_RS485) -#include "hal/transport/MyTransportHAL.h" -#include "core/MyTransport.h" - -// PARENT CHECK -#if defined(MY_PARENT_NODE_IS_STATIC) && (MY_PARENT_NODE_ID == AUTO) -#error Parent is static but no parent ID defined, set MY_PARENT_NODE_ID. -#endif - -#if defined(MY_TRANSPORT_DONT_CARE_MODE) -#error MY_TRANSPORT_DONT_CARE_MODE is deprecated, set MY_TRANSPORT_WAIT_READY_MS instead! -#endif - -// RAM ROUTING TABLE -#if defined(MY_RAM_ROUTING_TABLE_FEATURE) && defined(MY_REPEATER_FEATURE) -// activate feature based on architecture -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_NRF5) || defined(ARDUINO_ARCH_STM32F1) || defined(TEENSYDUINO) || defined(__linux__) -#define MY_RAM_ROUTING_TABLE_ENABLED -#elif defined(ARDUINO_ARCH_AVR) -#if defined(__avr_atmega1280__) || defined(__avr_atmega1284__) || defined(__avr_atmega2560__) -// >4kb, enable it -#define MY_RAM_ROUTING_TABLE_ENABLED -#else -// memory limited, enable with care -// #define MY_RAM_ROUTING_TABLE_ENABLED -#endif // __avr_atmega1280__, __avr_atmega1284__, __avr_atmega2560__ -#endif // ARDUINO_ARCH_AVR -#endif -#ifdef DOXYGEN -/** - * @def MY_RAM_ROUTING_TABLE_ENABLED - * @brief Automatically set if RAM routing table is enabled - * - * @see MY_RAM_ROUTING_TABLE_FEATURE - */ -#define MY_RAM_ROUTING_TABLE_ENABLED -#endif - -// SOFTSERIAL -#if defined(MY_GSM_TX) != defined(MY_GSM_RX) -#error Both, MY_GSM_TX and MY_GSM_RX need to be defined when using SoftSerial -#endif - -#if defined(MY_GATEWAY_TINYGSM) && !defined(SerialAT) && (!defined(MY_GSM_TX) || !defined(MY_GSM_RX)) -#error You need to define either SerialAT or MY_GSM_RX and MY_GSM_TX pins -#endif - -// POWER PIN -#ifndef DOXYGEN -#if defined(MY_RF24_POWER_PIN) || defined(MY_RFM69_POWER_PIN) || defined(MY_RFM95_POWER_PIN) || defined(MY_RADIO_NRF5_ESB) -#define RADIO_CAN_POWER_OFF (true) -#else -#define RADIO_CAN_POWER_OFF (false) -#endif -#endif - -// Transport drivers -#if defined(MY_RADIO_RF24) -#include "hal/transport/RF24/driver/RF24.cpp" -#include "hal/transport/RF24/MyTransportRF24.cpp" -#elif defined(MY_RADIO_NRF5_ESB) -#if !defined(ARDUINO_ARCH_NRF5) -#error No support for nRF5 radio on this platform -#endif -#include "hal/transport/NRF5_ESB/driver/Radio.cpp" -#include "hal/transport/NRF5_ESB/driver/Radio_ESB.cpp" -#include "hal/transport/NRF5_ESB/MyTransportNRF5_ESB.cpp" -#elif defined(MY_RS485) -#if !defined(MY_RS485_HWSERIAL) -#if defined(__linux__) -#error You must specify MY_RS485_HWSERIAL for RS485 transport -#endif -#include "drivers/AltSoftSerial/AltSoftSerial.cpp" -#endif -#include "hal/transport/RS485/MyTransportRS485.cpp" -#elif defined(MY_RADIO_RFM69) -#if defined(MY_RFM69_NEW_DRIVER) -#include "hal/transport/RFM69/driver/new/RFM69_new.cpp" -#else -#include "hal/transport/RFM69/driver/old/RFM69_old.cpp" -#endif -#include "hal/transport/RFM69/MyTransportRFM69.cpp" -#elif defined(MY_RADIO_RFM95) -#include "hal/transport/RFM95/driver/RFM95.cpp" -#include "hal/transport/RFM95/MyTransportRFM95.cpp" -#endif - -#if (defined(MY_RF24_ENABLE_ENCRYPTION) && defined(MY_RADIO_RF24)) || (defined(MY_NRF5_ESB_ENABLE_ENCRYPTION) && defined(MY_RADIO_NRF5_ESB)) || (defined(MY_RFM69_ENABLE_ENCRYPTION) && defined(MY_RADIO_RFM69)) || (defined(MY_RFM95_ENABLE_ENCRYPTION) && defined(MY_RADIO_RFM95)) -#define MY_TRANSPORT_ENCRYPTION //!< ïnternal flag -#endif - -#include "hal/transport/MyTransportHAL.cpp" - -// PASSIVE MODE -#if defined(MY_PASSIVE_NODE) && !defined(DOXYGEN) -#define MY_TRANSPORT_UPLINK_CHECK_DISABLED -#define MY_PARENT_NODE_IS_STATIC -#undef MY_REGISTRATION_FEATURE -#undef MY_SIGNING_FEATURE -#undef MY_OTA_FIRMWARE_FEATURE -#if defined(MY_GATEWAY_FEATURE) || defined(MY_REPEATER_FEATURE) -#error This node is configured as GW/repeater, MY_PASSIVE_NODE cannot be set simultaneously -#endif -#if (MY_NODE_ID == AUTO) -#error MY_PASSIVE_NODE configuration requires setting MY_NODE_ID -#endif -#endif - -#include "core/MyTransport.cpp" -#endif - -// Make sure to disable child features when parent feature is disabled -#if !defined(MY_SENSOR_NETWORK) -#undef MY_OTA_FIRMWARE_FEATURE -#undef MY_REPEATER_FEATURE -#undef MY_SIGNING_NODE_WHITELISTING -#undef MY_SIGNING_FEATURE -#endif - -#if !defined(MY_GATEWAY_FEATURE) -#undef MY_INCLUSION_MODE_FEATURE -#undef MY_INCLUSION_BUTTON_FEATURE -#endif - -#if !defined(MY_CORE_ONLY) -#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_SENSOR_NETWORK) -#error No forward link or gateway feature activated. This means nowhere to send messages! Pretty pointless. -#endif -#endif - -#include "core/MyCapabilities.h" -#include "core/MyMessage.cpp" -#include "core/MySplashScreen.cpp" -#include "core/MySensorsCore.cpp" - -// HW mains -#if defined(ARDUINO_ARCH_AVR) -#include "hal/architecture/AVR/MyMainAVR.cpp" -#elif defined(ARDUINO_ARCH_SAMD) -#include "hal/architecture/SAMD/MyMainSAMD.cpp" -#elif defined(ARDUINO_ARCH_ESP8266) -#include "hal/architecture/ESP8266/MyMainESP8266.cpp" -#elif defined(ARDUINO_ARCH_NRF5) -#include "hal/architecture/NRF5/MyMainNRF5.cpp" -#elif defined(ARDUINO_ARCH_ESP32) -#include "hal/architecture/ESP32/MyMainESP32.cpp" -#elif defined(__linux__) -#include "hal/architecture/Linux/MyMainLinuxGeneric.cpp" -#elif defined(ARDUINO_ARCH_STM32F1) -#include "hal/architecture/STM32F1/MyMainSTM32F1.cpp" -#elif defined(__arm__) && defined(TEENSYDUINO) -#include "hal/architecture/Teensy3/MyMainTeensy3.cpp" -#endif - -#endif - -/** @}*/ diff --git a/lib/MySensors/README.md b/lib/MySensors/README.md deleted file mode 100644 index 5e36c203..00000000 --- a/lib/MySensors/README.md +++ /dev/null @@ -1,19 +0,0 @@ -MySensors Library v2.3.2 - -Please visit www.mysensors.org for more information - -Current version in Arduino IDE [![arduino-library-badge](https://www.ardu-badge.com/badge/MySensors.svg)](https://www.ardu-badge.com/MySensors) - -Documentation -------------- -[master](https://www.mysensors.org/apidocs/index.html) [development](https://www.mysensors.org/apidocs-beta/index.html) - -CI statuses ------------ -Current build status of master branch: [![Build Status](https://ci.mysensors.org/job/MySensors/job/MySensors/job/master/badge/icon)](https://ci.mysensors.org/job/MySensors/job/MySensors/job/master/) - -Current build status of development branch: [![Build Status](https://ci.mysensors.org/job/MySensors/job/MySensors/job/development/badge/icon)](https://ci.mysensors.org/job/MySensors/job/MySensors/job/development/) - -Current build status of master branch (nightly build of Arduino IDE): [![Build Status](https://ci.mysensors.org/job/MySensors-nightly-IDE/job/MySensors/job/master/badge/icon)](https://ci.mysensors.org/job/MySensors-nightly-IDE/job/MySensors/job/master/) - -Current build status of development branch (nightly build of Arduino IDE): [![Build Status](https://ci.mysensors.org/job/MySensors-nightly-IDE/job/MySensors/job/development/badge/icon)](https://ci.mysensors.org/job/MySensors-nightly-IDE/job/MySensors/job/development/) \ No newline at end of file diff --git a/lib/MySensors/core/MyCapabilities.h b/lib/MySensors/core/MyCapabilities.h deleted file mode 100644 index 9c276c5e..00000000 --- a/lib/MySensors/core/MyCapabilities.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ -/** - * @file MyCapabilities.h - * @ingroup MyCapabilities - */ - -#ifndef MyCapabilities_h -#define MyCapabilities_h -/** - * @defgroup MyCapabilities Node capabilities indicator - * @ingroup MyConfigGrp - * - * @brief MySensors capabilities indications. - * - * At node startup, a capabilities string is shown as part of the initialization logs. - * This string indicate what configuration the node is running with. - * - * The string symbols are ordered in the following way: - * | Setting | Reset | Radio | OTA | Node | Architecture | Signing | Buffering | Encryption - * |-----------|-------------------|-------------------|--------------------|------------------|------------------|------------------|-------------------|----------------- - * | Indicator | @ref MY_CAP_RESET | @ref MY_CAP_RADIO | @ref MY_CAP_OTA_FW | @ref MY_CAP_TYPE | @ref MY_CAP_ARCH | @ref MY_CAP_SIGN | @ref MY_CAP_RXBUF | @ref MY_CAP_ENCR - * - * @see MY_CAPABILITIES - * - * @{ - */ - -// Remote reset -/** - * @def MY_CAP_RESET - * @brief Indicate the remote reset setting. - * - * @see MY_DISABLE_REMOTE_RESET - * - * | Setting | Indicator - * |------------|---------- - * | Enabled | R - * | Disabled | N - */ -#if defined(MY_DISABLE_REMOTE_RESET) -#define MY_CAP_RESET "N" -#else -#define MY_CAP_RESET "R" -#endif - -// OTA firmware update feature -/** - * @def MY_CAP_OTA_FW - * @brief Indicate the OTA update setting. - * - * @see MY_OTA_FIRMWARE_FEATURE - * - * | Setting | Indicator - * |------------|---------- - * | Enabled | O - * | Disabled | N - */ -#if defined(MY_OTA_FIRMWARE_FEATURE) -#define MY_CAP_OTA_FW "O" -#else -#define MY_CAP_OTA_FW "N" -#endif - -// Transport -/** - * @def MY_CAP_RADIO - * @brief Indicate the type of transport selected. - * - * @see MY_RADIO_RF24, MY_RADIO_NRF5_ESB, MY_RADIO_RFM69, MY_RFM69_NEW_DRIVER, MY_RADIO_RFM95, MY_RS485 - * - * | Radio | Indicator - * |--------------|---------- - * | nRF24/nRF5 | N - * | %RFM69 (old) | R - * | %RFM69 (new) | P - * | RFM95 | L - * | RS485 | S - * | None | - - */ -#if defined(MY_RADIO_RF24) || defined(MY_RADIO_NRF5_ESB) -#define MY_CAP_RADIO "N" -#elif defined(MY_RADIO_RFM69) -#if !defined(MY_RFM69_NEW_DRIVER) -// old RFM69 driver -#define MY_CAP_RADIO "R" -#else -// new RFM69 driver -#define MY_CAP_RADIO "P" -#endif -#elif defined(MY_RADIO_RFM95) -#define MY_CAP_RADIO "L" -#elif defined(MY_RS485) -#define MY_CAP_RADIO "S" -#else -#define MY_CAP_RADIO "-" -#endif - -// Node type -/** - * @def MY_CAP_TYPE - * @brief Indicate the type of node. - * - * @see MY_GATEWAY_FEATURE, MY_REPEATER_FEATURE, MY_PASSIVE_NODE - * - * | Node type | Indicator - * |-----------|---------- - * | Gateway | G - * | Repeater | R - * | Passive | P - * | Node | N - */ -#if defined(MY_GATEWAY_FEATURE) -#define MY_CAP_TYPE "G" -#elif defined(MY_REPEATER_FEATURE) -#define MY_CAP_TYPE "R" -#elif defined(MY_PASSIVE_NODE) -#define MY_CAP_TYPE "P" -#else -#define MY_CAP_TYPE "N" -#endif - -// Architecture -/** - * @def MY_CAP_ARCH - * @brief Indicate the architecture. - * - * @see ARDUINO_ARCH_SAMD, ARDUINO_ARCH_NRF5, ARDUINO_ARCH_ESP8266, ARDUINO_ARCH_AVR, ARDUINO_ARCH_STM32F1, TEENSYDUINO - * - * | Architecture | Indicator - * |--------------|---------- - * | SAMD | S - * | nRF5 | N - * | ESP8266 | E - * | AVR | A - * | STM32F1 | F - * | TEENSY | T - * | Linux | L - * | Unknown | - - */ -#if defined(ARDUINO_ARCH_SAMD) -#define MY_CAP_ARCH "S" -#elif defined(ARDUINO_ARCH_NRF5) -#define MY_CAP_ARCH "N" -#elif defined(ARDUINO_ARCH_ESP8266) -#define MY_CAP_ARCH "E" -#elif defined(ARDUINO_ARCH_ESP32) -#define MY_CAP_ARCH "F" -#elif defined(ARDUINO_ARCH_AVR) -#define MY_CAP_ARCH "A" -#elif defined(ARDUINO_ARCH_STM32F1) -#define MY_CAP_ARCH "F" -#elif defined(__arm__) && defined(TEENSYDUINO) -#define MY_CAP_ARCH "T" -#elif defined(__linux__) -#define MY_CAP_ARCH "L" -#else -#define MY_CAP_ARCH "-" -#endif - -// Signing -/** - * @def MY_CAP_SIGN - * @brief Indicate the signing backend used. - * - * @see MY_SIGNING_ATSHA204, MY_SIGNING_SOFT - * - * | Signing backend | Indicator - * |-----------------|---------- - * | ATSHA204 | A - * | Software | S - * | No signing | - - */ -#if defined(MY_SIGNING_ATSHA204) -#define MY_CAP_SIGN "A" -#elif defined(MY_SIGNING_SOFT) -#define MY_CAP_SIGN "S" -#else -#define MY_CAP_SIGN "-" -#endif - -// RX queue -/** - * @def MY_CAP_RXBUF - * @brief Indicate the rx message buffer setting. - * - * @see MY_RX_MESSAGE_BUFFER_FEATURE - * - * | Setting | Indicator - * |------------|---------- - * | Enabled | Q - * | Disabled | - - */ -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -#define MY_CAP_RXBUF "Q" -#else -#define MY_CAP_RXBUF "-" -#endif - -// Radio encryption -/** - * @def MY_CAP_ENCR - * @brief Indicate the encryption setting. - * - * @see MY_ENCRYPTION_FEATURE - * - * | Setting | Indicator - * |------------|---------- - * | Enabled | X - * | Disabled | - - */ -#if defined(MY_ENCRYPTION_FEATURE) -#define MY_CAP_ENCR "X" -#else -#define MY_CAP_ENCR "-" -#endif - - -/** - * @def MY_CAPABILITIES - * @brief This is the resulting capabilities string. - * - * @see MY_CAP_RESET, MY_CAP_RADIO, MY_CAP_OTA_FW, MY_CAP_TYPE, MY_CAP_ARCH, MY_CAP_SIGN, MY_CAP_RXBUF, MY_CAP_ENCR - */ -#define MY_CAPABILITIES MY_CAP_RESET MY_CAP_RADIO MY_CAP_OTA_FW MY_CAP_TYPE MY_CAP_ARCH MY_CAP_SIGN MY_CAP_RXBUF MY_CAP_ENCR - -/** @}*/ // End of MyCapabilities group -#endif /* MyCapabilities_h */ diff --git a/lib/MySensors/core/MyEepromAddresses.h b/lib/MySensors/core/MyEepromAddresses.h deleted file mode 100644 index 8e735e06..00000000 --- a/lib/MySensors/core/MyEepromAddresses.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** -* @file MyEepromAddresses.h -* @brief Eeprom addresses for MySensors library data -* -* @defgroup MyEepromAddressesgrp MyEepromAddresses -* @ingroup internals -* @{ -* -*/ - - -#ifndef MyEepromAddresses_h -#define MyEepromAddresses_h - -// EEPROM variable sizes, in bytes -#define SIZE_NODE_ID (1u) //!< Size node ID -#define SIZE_PARENT_NODE_ID (1u) //!< Size parent node ID -#define SIZE_DISTANCE (1u) //!< Size GW distance -#define SIZE_ROUTES (256u) //!< Size routing table -#define SIZE_CONTROLLER_CONFIG (23u) //!< Size controller config -#define SIZE_PERSONALIZATION_CHECKSUM (1u) //!< Size personalization checksum -#define SIZE_FIRMWARE_TYPE (2u) //!< Size firmware type -#define SIZE_FIRMWARE_VERSION (2u) //!< Size firmware version -#define SIZE_FIRMWARE_BLOCKS (2u) //!< Size firmware blocks -#define SIZE_FIRMWARE_CRC (2u) //!< Size firmware CRC -#define SIZE_SIGNING_REQUIREMENT_TABLE (32u) //!< Size signing requirement table -#define SIZE_WHITELIST_REQUIREMENT_TABLE (32u) //!< Size whitelist requirement table -#define SIZE_SIGNING_SOFT_HMAC_KEY (32u) //!< Size soft signing HMAC key -#define SIZE_SIGNING_SOFT_SERIAL (9u) //!< Size soft signing serial -#define SIZE_RF_ENCRYPTION_AES_KEY (16u) //!< Size RF AES encryption key -#define SIZE_NODE_LOCK_COUNTER (1u) //!< Size node lock counter - - -/** @brief EEPROM start address */ -#define EEPROM_START (0u) -/** @brief Address node ID */ -#define EEPROM_NODE_ID_ADDRESS EEPROM_START -/** @brief Address parent node ID */ -#define EEPROM_PARENT_NODE_ID_ADDRESS (EEPROM_NODE_ID_ADDRESS + SIZE_NODE_ID) -/** @brief Address distance to GW */ -#define EEPROM_DISTANCE_ADDRESS (EEPROM_PARENT_NODE_ID_ADDRESS + SIZE_PARENT_NODE_ID) -/** @brief Address routing table */ -#define EEPROM_ROUTES_ADDRESS (EEPROM_DISTANCE_ADDRESS + SIZE_DISTANCE) -/** @brief Address configuration bytes sent by controller */ -#define EEPROM_CONTROLLER_CONFIG_ADDRESS (EEPROM_ROUTES_ADDRESS + SIZE_ROUTES) -/** @brief Personalization checksum (set by SecurityPersonalizer.ino) */ -#define EEPROM_PERSONALIZATION_CHECKSUM_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS + SIZE_CONTROLLER_CONFIG) -/** @brief Address firmware type */ -#define EEPROM_FIRMWARE_TYPE_ADDRESS (EEPROM_PERSONALIZATION_CHECKSUM_ADDRESS + SIZE_PERSONALIZATION_CHECKSUM) -/** @brief Address firmware version */ -#define EEPROM_FIRMWARE_VERSION_ADDRESS (EEPROM_FIRMWARE_TYPE_ADDRESS + SIZE_FIRMWARE_TYPE) -/** @brief Address firmware blocks */ -#define EEPROM_FIRMWARE_BLOCKS_ADDRESS (EEPROM_FIRMWARE_VERSION_ADDRESS + SIZE_FIRMWARE_VERSION) -/** @brief Address firmware CRC */ -#define EEPROM_FIRMWARE_CRC_ADDRESS (EEPROM_FIRMWARE_BLOCKS_ADDRESS + SIZE_FIRMWARE_BLOCKS) -/** @brief Address signing requirement table */ -#define EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS + SIZE_FIRMWARE_CRC) -/** @brief Address whitelist requirement table */ -#define EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS (EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS + SIZE_SIGNING_REQUIREMENT_TABLE) -/** @brief Address soft signing HMAC key. This is set with @ref SecurityPersonalizer.ino */ -#define EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS (EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS + SIZE_WHITELIST_REQUIREMENT_TABLE) -/** @brief Address soft signing serial key. This is set with @ref SecurityPersonalizer.ino */ -#define EEPROM_SIGNING_SOFT_SERIAL_ADDRESS (EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS + SIZE_SIGNING_SOFT_HMAC_KEY) -/** @brief Address RF AES encryption key. This is set with @ref SecurityPersonalizer.ino */ -#define EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS (EEPROM_SIGNING_SOFT_SERIAL_ADDRESS + SIZE_SIGNING_SOFT_SERIAL) -/** @brief Address node lock counter. This is set with @ref SecurityPersonalizer.ino */ -#define EEPROM_NODE_LOCK_COUNTER_ADDRESS (EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS + SIZE_RF_ENCRYPTION_AES_KEY) -/** @brief First free address for sketch static configuration */ -#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_NODE_LOCK_COUNTER_ADDRESS + SIZE_NODE_LOCK_COUNTER) - -#endif // MyEepromAddresses_h - -/** @}*/ diff --git a/lib/MySensors/core/MyGatewayTransport.cpp b/lib/MySensors/core/MyGatewayTransport.cpp deleted file mode 100644 index 37aa7132..00000000 --- a/lib/MySensors/core/MyGatewayTransport.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Tomas Hozza - * Copyright (C) 2015 Tomas Hozza - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyGatewayTransport.h" - -extern bool transportSendRoute(MyMessage &message); - -// global variables -extern MyMessage _msg; -extern MyMessage _msgTmp; - -inline void gatewayTransportProcess(void) -{ - if (gatewayTransportAvailable()) { - _msg = gatewayTransportReceive(); - if (_msg.getDestination() == GATEWAY_ADDRESS) { - - // Check if sender requests an echo - if (_msg.getRequestEcho()) { - // Copy message - _msgTmp = _msg; - // Reply without echo flag, otherwise we would end up in an eternal loop - _msgTmp.setRequestEcho(false); - _msgTmp.setEcho(true); - _msgTmp.setSender(getNodeId()); - _msgTmp.setDestination(_msg.getSender()); - gatewayTransportSend(_msgTmp); - } - if (_msg.getCommand() == C_INTERNAL) { - if (_msg.getType() == I_VERSION) { - // Request for version. Create the response - gatewayTransportSend(buildGw(_msgTmp, I_VERSION).set(MYSENSORS_LIBRARY_VERSION)); -#ifdef MY_INCLUSION_MODE_FEATURE - } else if (_msg.getType() == I_INCLUSION_MODE) { - // Request to change inclusion mode - inclusionModeSet(atoi(_msg.data) == 1); -#endif - } else { - (void)_processInternalCoreMessage(); - } - } else { - // Call incoming message callback if available - if (receive) { - receive(_msg); - } - } - } else { -#if defined(MY_SENSOR_NETWORK) - transportSendRoute(_msg); -#endif - } - } -} diff --git a/lib/MySensors/core/MyGatewayTransport.h b/lib/MySensors/core/MyGatewayTransport.h deleted file mode 100644 index cfb34b48..00000000 --- a/lib/MySensors/core/MyGatewayTransport.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Tomas Hozza - * Copyright (C) 2015 Tomas Hozza - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** -* @file MyGatewayTransport.h -* -* @defgroup MyGatewayTransportgrp MyGatewayTransport -* @ingroup internals -* @{ -* -* Gateway transport-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE -* - [!] Exclamation mark is prepended in case of error -* - SYSTEM: -* - GWT: messages emitted by MyGatewayTransport -* - SUB SYSTEMS: -* - GWT:TIN from @ref gatewayTransportInit() -* - GWT:TPS from @ref gatewayTransportSend() -* - GWT:IMQ from incomingMQTT() -* - GWT:RMQ from reconnectMQTT() -* - GWT:TPC from gatewayTransportConnect() -* - GWT:RFC from _readFromClient() -* - GWT:TSA from @ref gatewayTransportAvailable() -* - GWT:TRC from @ref gatewayTransportReceive() -* -* Gateway transport debug log messages : -* -* |E| SYS | SUB | Message | Comment -* |-|-----|-------|---------------------------|--------------------------------------------------------------------- -* | | GWT | TIN | CONNECTING... | Connecting to router -* | | GWT | TIN | IP=%%s | IP address [%%s] obtained -* |!| GWT | TIN | DHCP FAIL | DHCP request failed -* | | GWT | TIN | ETH OK | Connected to network -* |!| GWT | TIN | ETH FAIL | Connection failed -* | | GWT | TPS | TOPIC=%%s,MSG SENT | MQTT message sent on topic [%%s] -* | | GWT | TPS | ETH OK | Connected to network -* |!| GWT | TPS | ETH FAIL | Connection failed -* | | GWT | IMQ | TOPIC=%%s,MSG RECEIVE | MQTT message received on topic [%%s] -* | | GWT | RMQ | CONNECTING... | Connecting to MQTT broker -* | | GWT | RMQ | OK | Connected to MQTT broker -* |!| GWT | RMQ | FAIL | Connection to MQTT broker failed -* | | GWT | TPC | CONNECTING... | Obtaining IP address -* | | GWT | TPC | IP=%%s | IP address [%%s] obtained -* |!| GWT | TPC | DHCP FAIL | DHCP request failed -* | | GWT | RFC | C=%%d,MSG=%%s | Received message [%%s] from client [%%d] -* |!| GWT | RFC | C=%%d,MSG TOO LONG | Received message from client [%%d] too long -* | | GWT | TSA | UDP MSG=%%s | Received UDP message [%%s] -* | | GWT | TSA | ETH OK | Connected to network -* |!| GWT | TSA | ETH FAIL | Connection failed -* | | GWT | TSA | C=%d,DISCONNECTED | Client [%%d] disconnected -* | | GWT | TSA | C=%d,CONNECTED | Client [%%d] connected -* |!| GWT | TSA | NO FREE SLOT | No free slot for client -* |!| GWT | TRC | IP RENEW FAIL | IP renewal failed -* -* @brief API declaration for MyGatewayTransport -* -*/ - -#ifndef MyGatewayTransport_h -#define MyGatewayTransport_h - -#include "MyProtocol.h" -#include "MySensorsCore.h" - -#define MSG_GW_STARTUP_COMPLETE "Gateway startup complete." //!< Gateway startup message - -#if defined(MY_DEBUG_VERBOSE_GATEWAY) -#define GATEWAY_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< debug output -#else -#define GATEWAY_DEBUG(x,...) //!< debug NULL -#endif - -/** - * @brief Process gateway-related messages - */ -void gatewayTransportProcess(void); - -/** - * @brief Initialize gateway transport driver - * @return true if transport initialized - */ -bool gatewayTransportInit(void); - -/** - * @brief Send message to controller - * @param message to send - * @return true if message delivered - */ -bool gatewayTransportSend(MyMessage &message); - -/** - * @brief Check if a new message is available from controller - * @return true if message available - */ -bool gatewayTransportAvailable(void); - -/** - * @brief Pick up last message received from controller - * @return message - */ -MyMessage& gatewayTransportReceive(void); - -#endif /* MyGatewayTransportEthernet_h */ - -/** @}*/ - diff --git a/lib/MySensors/core/MyGatewayTransportEthernet.cpp b/lib/MySensors/core/MyGatewayTransportEthernet.cpp deleted file mode 100644 index dde3a69e..00000000 --- a/lib/MySensors/core/MyGatewayTransportEthernet.cpp +++ /dev/null @@ -1,495 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Tomas Hozza - * Copyright (C) 2015 Tomas Hozza - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyGatewayTransport.h" - -// global variables -extern MyMessage _msgTmp; - -// housekeeping, remove for 3.0.0 -#ifdef MY_ESP8266_SSID -#warning MY_ESP8266_SSID is deprecated, use MY_WIFI_SSID instead! -#define MY_WIFI_SSID MY_ESP8266_SSID -#undef MY_ESP8266_SSID // cleanup -#endif - -#ifdef MY_ESP8266_PASSWORD -#warning MY_ESP8266_PASSWORD is deprecated, use MY_WIFI_PASSWORD instead! -#define MY_WIFI_PASSWORD MY_ESP8266_PASSWORD -#undef MY_ESP8266_PASSWORD // cleanup -#endif - -#ifdef MY_ESP8266_BSSID -#warning MY_ESP8266_BSSID is deprecated, use MY_WIFI_BSSID instead! -#define MY_WIFI_BSSID MY_ESP8266_BSSID -#undef MY_ESP8266_BSSID // cleanup -#endif - -#ifdef MY_ESP8266_HOSTNAME -#warning MY_ESP8266_HOSTNAME is deprecated, use MY_HOSTNAME instead! -#define MY_HOSTNAME MY_ESP8266_HOSTNAME -#undef MY_ESP8266_HOSTNAME // cleanup -#endif - -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -#if !defined(MY_WIFI_SSID) -#error ESP8266/ESP32 gateway: MY_WIFI_SSID not defined! -#endif -#endif - -#if defined(MY_CONTROLLER_IP_ADDRESS) -#define _ethernetControllerIP IPAddress(MY_CONTROLLER_IP_ADDRESS) -#endif - -#if defined(MY_IP_ADDRESS) -#define _ethernetGatewayIP IPAddress(MY_IP_ADDRESS) -#if defined(MY_IP_GATEWAY_ADDRESS) -#define _gatewayIp IPAddress(MY_IP_GATEWAY_ADDRESS) -#elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -// Assume the gateway will be the machine on the same network as the local IP -// but with last octet being '1' -#define _gatewayIp IPAddress(_ethernetGatewayIP[0], _ethernetGatewayIP[1], _ethernetGatewayIP[2], 1) -#endif /* End of MY_IP_GATEWAY_ADDRESS */ -#if defined(MY_IP_SUBNET_ADDRESS) -#define _subnetIp IPAddress(MY_IP_SUBNET_ADDRESS) -#elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -#define _subnetIp IPAddress(255, 255, 255, 0) -#endif /* End of MY_IP_SUBNET_ADDRESS */ -#endif /* End of MY_IP_ADDRESS */ - -uint8_t _ethernetGatewayMAC[] = { MY_MAC_ADDRESS }; -uint16_t _ethernetGatewayPort = MY_PORT; -MyMessage _ethernetMsg; - -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) - -typedef struct { - // Suppress the warning about unused members in this struct because it is used through a complex - // set of preprocessor directives - // cppcheck-suppress unusedStructMember - char string[MY_GATEWAY_MAX_RECEIVE_LENGTH]; - // cppcheck-suppress unusedStructMember - uint8_t idx; -} inputBuffer; - -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -// Some re-defines to make code more readable below -#define EthernetServer WiFiServer -#define EthernetClient WiFiClient -#define EthernetUDP WiFiUDP -#endif - -#if defined(MY_GATEWAY_CLIENT_MODE) -#if defined(MY_USE_UDP) -EthernetUDP _ethernetServer; -#endif /* End of MY_USE_UDP */ -#elif defined(MY_GATEWAY_LINUX) /* Elif part of MY_GATEWAY_CLIENT_MODE */ -EthernetServer _ethernetServer(_ethernetGatewayPort, MY_GATEWAY_MAX_CLIENTS); -#else /* Else part of MY_GATEWAY_CLIENT_MODE */ -EthernetServer _ethernetServer(_ethernetGatewayPort); -#endif /* End of MY_GATEWAY_CLIENT_MODE */ - -#if defined(MY_GATEWAY_CLIENT_MODE) -static inputBuffer inputString; -#if defined(MY_USE_UDP) -// Nothing to do here -#else -static EthernetClient client = EthernetClient(); -#endif /* End of MY_USE_UDP */ -#elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) || defined(MY_GATEWAY_LINUX) -static EthernetClient clients[MY_GATEWAY_MAX_CLIENTS]; -static bool clientsConnected[MY_GATEWAY_MAX_CLIENTS]; -static inputBuffer inputString[MY_GATEWAY_MAX_CLIENTS]; -#else /* Else part of MY_GATEWAY_CLIENT_MODE */ -static EthernetClient client = EthernetClient(); -static inputBuffer inputString; -#endif /* End of MY_GATEWAY_CLIENT_MODE */ - -// On W5100 boards with SPI_EN exposed we can use the real SPI bus together with radio -// (if we enable it during usage) -void _w5100_spi_en(const bool enable) -{ -#if defined(MY_W5100_SPI_EN) - if (enable) { - // Pull up pin - hwPinMode(MY_W5100_SPI_EN, INPUT); - hwDigitalWrite(MY_W5100_SPI_EN, HIGH); - } else { - // Ground pin - hwPinMode(MY_W5100_SPI_EN, OUTPUT); - hwDigitalWrite(MY_W5100_SPI_EN, LOW); - } -#else - (void)enable; -#endif -} - -#if !defined(MY_IP_ADDRESS) && defined(MY_GATEWAY_W5100) -void gatewayTransportRenewIP(void) -{ - /* renew/rebind IP address - 0 - nothing happened - 1 - renew failed - 2 - renew success - 3 - rebind failed - 4 - rebind success - */ - static uint32_t _nextIPRenewal = hwMillis() + MY_IP_RENEWAL_INTERVAL_MS; - const uint32_t now = hwMillis(); - - // http://playground.arduino.cc/Code/TimingRollover - if ((int32_t)(now - _nextIPRenewal) < 0) { - return; - } - if (Ethernet.maintain() & ~(0x06)) { - GATEWAY_DEBUG(PSTR("!GWT:TRC:IP RENEW FAIL\n")); - return; - } - _w5100_spi_en(false); - _nextIPRenewal = now + MY_IP_RENEWAL_INTERVAL_MS; -} -#endif - -bool gatewayTransportInit(void) -{ - _w5100_spi_en(true); - -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) - // Turn off access point - WiFi.mode(WIFI_STA); -#if defined(MY_GATEWAY_ESP8266) - WiFi.hostname(MY_HOSTNAME); -#elif defined(MY_GATEWAY_ESP32) - WiFi.setHostname(MY_HOSTNAME); -#endif -#ifdef MY_IP_ADDRESS - WiFi.config(_ethernetGatewayIP, _gatewayIp, _subnetIp); -#endif - (void)WiFi.begin(MY_WIFI_SSID, MY_WIFI_PASSWORD, 0, MY_WIFI_BSSID); - while (WiFi.status() != WL_CONNECTED) { - delay(1000); - GATEWAY_DEBUG(PSTR("GWT:TIN:CONNECTING...\n")); - } - GATEWAY_DEBUG(PSTR("GWT:TIN:IP: %s\n"), WiFi.localIP().toString().c_str()); -#elif defined(MY_GATEWAY_LINUX) - // Nothing to do here -#else -#if defined(MY_IP_GATEWAY_ADDRESS) && defined(MY_IP_SUBNET_ADDRESS) - // DNS server set to gateway ip - Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP, _gatewayIp, _gatewayIp, _subnetIp); -#elif defined(MY_IP_ADDRESS) - Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP); -#else /* Else part of MY_IP_GATEWAY_ADDRESS && MY_IP_SUBNET_ADDRESS */ - // Get IP address from DHCP - if (!Ethernet.begin(_ethernetGatewayMAC)) { - GATEWAY_DEBUG(PSTR("!GWT:TIN:DHCP FAIL\n")); - _w5100_spi_en(false); - return false; - } -#endif /* End of MY_IP_GATEWAY_ADDRESS && MY_IP_SUBNET_ADDRESS */ - GATEWAY_DEBUG(PSTR("GWT:TIN:IP=%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "\n"), - Ethernet.localIP()[0], - Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]); - // give the Ethernet interface a second to initialize - delay(1000); -#endif /* MY_GATEWAY_ESP8266 / MY_GATEWAY_ESP32 */ - -#if defined(MY_GATEWAY_CLIENT_MODE) -#if defined(MY_USE_UDP) - _ethernetServer.begin(_ethernetGatewayPort); -#else /* Else part of MY_USE_UDP */ -#if defined(MY_GATEWAY_LINUX) && defined(MY_IP_ADDRESS) - client.bind(_ethernetGatewayIP); -#endif /* End of MY_GATEWAY_LINUX && MY_IP_ADDRESS */ -#if defined(MY_CONTROLLER_URL_ADDRESS) - if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { -#else - if (client.connect(_ethernetControllerIP, MY_PORT)) { -#endif /* End of MY_CONTROLLER_URL_ADDRESS */ - GATEWAY_DEBUG(PSTR("GWT:TIN:ETH OK\n")); - _w5100_spi_en(false); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set(F(MSG_GW_STARTUP_COMPLETE))); - _w5100_spi_en(true); - presentNode(); - } else { - client.stop(); - GATEWAY_DEBUG(PSTR("!GWT:TIN:ETH FAIL\n")); - } -#endif /* End of MY_USE_UDP */ -#else /* Else part of MY_GATEWAY_CLIENT_MODE */ -#if defined(MY_GATEWAY_LINUX) && defined(MY_IP_ADDRESS) - _ethernetServer.begin(_ethernetGatewayIP); -#else - // we have to use pointers due to the constructor of EthernetServer - _ethernetServer.begin(); -#endif /* End of MY_GATEWAY_LINUX && MY_IP_ADDRESS */ -#endif /* End of MY_GATEWAY_CLIENT_MODE */ - - _w5100_spi_en(false); - return true; -} - -bool gatewayTransportSend(MyMessage &message) -{ - int nbytes = 0; - char *_ethernetMessage = protocolMyMessage2Serial(message); - - setIndication(INDICATION_GW_TX); - - _w5100_spi_en(true); -#if defined(MY_GATEWAY_CLIENT_MODE) -#if defined(MY_USE_UDP) -#if defined(MY_CONTROLLER_URL_ADDRESS) - _ethernetServer.beginPacket(MY_CONTROLLER_URL_ADDRESS, MY_PORT); -#else - _ethernetServer.beginPacket(_ethernetControllerIP, MY_PORT); -#endif /* End of MY_CONTROLLER_URL_ADDRESS */ - _ethernetServer.write((uint8_t *)_ethernetMessage, strlen(_ethernetMessage)); - // returns 1 if the packet was sent successfully - nbytes = _ethernetServer.endPacket(); -#else /* Else part of MY_USE_UDP */ - if (!client.connected()) { - client.stop(); -#if defined(MY_CONTROLLER_URL_ADDRESS) - if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { -#else - if (client.connect(_ethernetControllerIP, MY_PORT)) { -#endif /* End of MY_CONTROLLER_URL_ADDRESS */ - GATEWAY_DEBUG(PSTR("GWT:TPS:ETH OK\n")); - _w5100_spi_en(false); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set(MSG_GW_STARTUP_COMPLETE)); - _w5100_spi_en(true); - presentNode(); - } else { - // connecting to the server failed! - GATEWAY_DEBUG(PSTR("!GWT:TPS:ETH FAIL\n")); - _w5100_spi_en(false); - return false; - } - } - nbytes = client.write((const uint8_t *)_ethernetMessage, strlen(_ethernetMessage)); -#endif /* End of MY_USE_UDP */ -#else /* Else part of MY_GATEWAY_CLIENT_MODE */ - // Send message to connected clients -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i] && clients[i].connected()) { - nbytes += clients[i].write((uint8_t *)_ethernetMessage, strlen(_ethernetMessage)); - } - } -#else /* Else part of MY_GATEWAY_ESPxx*/ - nbytes = _ethernetServer.write(_ethernetMessage); -#endif /* End of MY_GATEWAY_ESPxx */ -#endif /* End of MY_GATEWAY_CLIENT_MODE */ - _w5100_spi_en(false); - return (nbytes > 0); -} - -#if defined(MY_USE_UDP) -// Nothing to do here -#else -#if (defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) || defined(MY_GATEWAY_LINUX)) && !defined(MY_GATEWAY_CLIENT_MODE) -bool _readFromClient(uint8_t i) -{ - while (clients[i].connected() && clients[i].available()) { - const char inChar = clients[i].read(); - if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { - // if newline then command is complete - if (inChar == '\n' || inChar == '\r') { - // Add string terminator and prepare for the next message - inputString[i].string[inputString[i].idx] = 0; - GATEWAY_DEBUG(PSTR("GWT:RFC:C=%" PRIu8 ",MSG=%s\n"), i, inputString[i].string); - inputString[i].idx = 0; - if (protocolSerial2MyMessage(_ethernetMsg, inputString[i].string)) { - return true; - } - } else { - // add it to the inputString: - inputString[i].string[inputString[i].idx++] = inChar; - } - } else { - // Incoming message too long. Throw away - GATEWAY_DEBUG(PSTR("!GWT:RFC:C=%" PRIu8 ",MSG TOO LONG\n"), i); - inputString[i].idx = 0; - // Finished with this client's message. Next loop() we'll see if there's more to read. - break; - } - } - return false; -} -#else /* Else part of MY_GATEWAY_ESP8266 || MY_GATEWAY_LINUX || !MY_GATEWAY_CLIENT_MODE */ -bool _readFromClient(void) -{ - while (client.connected() && client.available()) { - const char inChar = client.read(); - if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { - // if newline then command is complete - if (inChar == '\n' || inChar == '\r') { - // Add string terminator and prepare for the next message - inputString.string[inputString.idx] = 0; - GATEWAY_DEBUG(PSTR("GWT:RFC:MSG=%s\n"), inputString.string); - inputString.idx = 0; - if (protocolSerial2MyMessage(_ethernetMsg, inputString.string)) { - return true; - } - - } else { - // add it to the inputString: - inputString.string[inputString.idx++] = inChar; - } - } else { - // Incoming message too long. Throw away - GATEWAY_DEBUG(PSTR("!GWT:RFC:MSG TOO LONG\n")); - inputString.idx = 0; - // Finished with this client's message. Next loop() we'll see if there's more to read. - break; - } - } - return false; -} -#endif /* End of MY_GATEWAY_ESP8266 || MY_GATEWAY_LINUX || !MY_GATEWAY_CLIENT_MODE */ -#endif /* End of MY_USE_UDP */ - -bool gatewayTransportAvailable(void) -{ - _w5100_spi_en(true); -#if !defined(MY_IP_ADDRESS) && defined(MY_GATEWAY_W5100) - // renew IP address using DHCP - gatewayTransportRenewIP(); -#endif - -#if defined(MY_GATEWAY_CLIENT_MODE) -#if defined(MY_USE_UDP) - int packet_size = _ethernetServer.parsePacket(); - - if (packet_size) { - _ethernetServer.read(inputString.string, MY_GATEWAY_MAX_RECEIVE_LENGTH); - inputString.string[packet_size] = 0; - GATEWAY_DEBUG(PSTR("GWT:TSA:UDP MSG=%s\n"), inputString.string); - _w5100_spi_en(false); - const bool ok = protocolSerial2MyMessage(_ethernetMsg, inputString.string); - if (ok) { - setIndication(INDICATION_GW_RX); - } - return ok; - } -#else /* Else part of MY_USE_UDP */ - if (!client.connected()) { - client.stop(); -#if defined(MY_CONTROLLER_URL_ADDRESS) - if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { -#else - if (client.connect(_ethernetControllerIP, MY_PORT)) { -#endif /* End of MY_CONTROLLER_URL_ADDRESS */ - GATEWAY_DEBUG(PSTR("GWT:TSA:ETH OK\n")); - _w5100_spi_en(false); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set(F(MSG_GW_STARTUP_COMPLETE))); - _w5100_spi_en(true); - presentNode(); - } else { - GATEWAY_DEBUG(PSTR("!GWT:TSA:ETH FAIL\n")); - _w5100_spi_en(false); - return false; - } - } - if (_readFromClient()) { - setIndication(INDICATION_GW_RX); - _w5100_spi_en(false); - return true; - } -#endif /* End of MY_USE_UDP */ -#else /* Else part of MY_GATEWAY_CLIENT_MODE */ -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) || defined(MY_GATEWAY_LINUX) - // ESP8266/ESP32: Go over list of clients and stop any that are no longer connected. - // If the server has a new client connection it will be assigned to a free slot. - bool allSlotsOccupied = true; - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { - if (!clients[i].connected()) { - if (clientsConnected[i]) { - GATEWAY_DEBUG(PSTR("GWT:TSA:C=%" PRIu8 ",DISCONNECTED\n"), i); - clients[i].stop(); - } - //check if there are any new clients - if (_ethernetServer.hasClient()) { - clients[i] = _ethernetServer.available(); - inputString[i].idx = 0; - GATEWAY_DEBUG(PSTR("GWT:TSA:C=%" PRIu8 ",CONNECTED\n"), i); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set(MSG_GW_STARTUP_COMPLETE)); - // Send presentation of locally attached sensors (and node if applicable) - presentNode(); - } - } - bool connected = clients[i].connected(); - clientsConnected[i] = connected; - allSlotsOccupied &= connected; - } - if (allSlotsOccupied && _ethernetServer.hasClient()) { - //no free/disconnected spot so reject - GATEWAY_DEBUG(PSTR("!GWT:TSA:NO FREE SLOT\n")); - EthernetClient c = _ethernetServer.available(); - c.stop(); - } - // Loop over clients connect and read available data - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { - if (_readFromClient(i)) { - setIndication(INDICATION_GW_RX); - _w5100_spi_en(false); - return true; - } - } -#else /* Else part of MY_GATEWAY_ESP8266 || MY_GATEWAY_LINUX */ - // W5100/ENC module does not have hasClient-method. We can only serve one client at the time. - EthernetClient newclient = _ethernetServer.available(); - // if a new client connects make sure to dispose any previous existing sockets - if (newclient) { - if (client != newclient) { - client.stop(); - client = newclient; - GATEWAY_DEBUG(PSTR("GWT:TSA:ETH OK\n")); - _w5100_spi_en(false); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set(MSG_GW_STARTUP_COMPLETE)); - _w5100_spi_en(true); - presentNode(); - } - } - if (client) { - if (!client.connected()) { - GATEWAY_DEBUG(PSTR("!GWT:TSA:ETH FAIL\n")); - client.stop(); - } else { - if (_readFromClient()) { - setIndication(INDICATION_GW_RX); - _w5100_spi_en(false); - return true; - } - } - } -#endif /* End of MY_GATEWAY_ESP8266 || MY_GATEWAY_LINUX */ -#endif /* End of MY_GATEWAY_CLIENT_MODE */ - _w5100_spi_en(false); - return false; -} - -MyMessage& gatewayTransportReceive(void) -{ - // Return the last parsed message - return _ethernetMsg; -} - - diff --git a/lib/MySensors/core/MyGatewayTransportMQTTClient.cpp b/lib/MySensors/core/MyGatewayTransportMQTTClient.cpp deleted file mode 100644 index 12cfd67e..00000000 --- a/lib/MySensors/core/MyGatewayTransportMQTTClient.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - - -// Topic structure: MY_MQTT_PUBLISH_TOPIC_PREFIX/NODE-ID/SENSOR-ID/CMD-TYPE/ACK-FLAG/SUB-TYPE - -#include "MyGatewayTransport.h" - -// housekeeping, remove for 3.0.0 -#ifdef MY_ESP8266_SSID -#warning MY_ESP8266_SSID is deprecated, use MY_WIFI_SSID instead! -#define MY_WIFI_SSID MY_ESP8266_SSID -#undef MY_ESP8266_SSID // cleanup -#endif - -#ifdef MY_ESP8266_PASSWORD -#warning MY_ESP8266_PASSWORD is deprecated, use MY_WIFI_PASSWORD instead! -#define MY_WIFI_PASSWORD MY_ESP8266_PASSWORD -#undef MY_ESP8266_PASSWORD // cleanup -#endif - -#ifdef MY_ESP8266_BSSID -#warning MY_ESP8266_BSSID is deprecated, use MY_WIFI_BSSID instead! -#define MY_WIFI_BSSID MY_ESP8266_BSSID -#undef MY_ESP8266_BSSID // cleanup -#endif - -#ifdef MY_ESP8266_HOSTNAME -#warning MY_ESP8266_HOSTNAME is deprecated, use MY_HOSTNAME instead! -#define MY_HOSTNAME MY_ESP8266_HOSTNAME -#undef MY_ESP8266_HOSTNAME // cleanup -#endif - -#ifndef MY_MQTT_USER -#define MY_MQTT_USER NULL -#endif - -#ifndef MY_MQTT_PASSWORD -#define MY_MQTT_PASSWORD NULL -#endif - -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -#if !defined(MY_WIFI_SSID) -#error ESP8266/ESP32 MQTT gateway: MY_WIFI_SSID not defined! -#endif -#endif - -#if defined MY_CONTROLLER_IP_ADDRESS -#define _brokerIp IPAddress(MY_CONTROLLER_IP_ADDRESS) -#endif - -#if defined(MY_IP_ADDRESS) -#define _MQTT_clientIp IPAddress(MY_IP_ADDRESS) -#if defined(MY_IP_GATEWAY_ADDRESS) -#define _gatewayIp IPAddress(MY_IP_GATEWAY_ADDRESS) -#elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -// Assume the gateway will be the machine on the same network as the local IP -// but with last octet being '1' -#define _gatewayIp IPAddress(_MQTT_clientIp[0], _MQTT_clientIp[1], _MQTT_clientIp[2], 1) -#endif /* End of MY_IP_GATEWAY_ADDRESS */ - -#if defined(MY_IP_SUBNET_ADDRESS) -#define _subnetIp IPAddress(MY_IP_SUBNET_ADDRESS) -#elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -#define _subnetIp IPAddress(255, 255, 255, 0) -#endif /* End of MY_IP_SUBNET_ADDRESS */ -#endif /* End of MY_IP_ADDRESS */ - -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) -#define EthernetClient WiFiClient -#elif defined(MY_GATEWAY_LINUX) -// Nothing to do here -#else -uint8_t _MQTT_clientMAC[] = { MY_MAC_ADDRESS }; -#endif /* End of MY_GATEWAY_ESPxy */ - -#if defined(MY_GATEWAY_TINYGSM) -#if defined(MY_GSM_RX) && defined(MY_GSM_TX) -SoftwareSerial SerialAT(MY_GSM_RX, MY_GSM_TX); -#endif -static TinyGsm modem(SerialAT); -static TinyGsmClient _MQTT_ethClient(modem); -#if defined(MY_GSM_BAUDRATE) -uint32_t rate = MY_GSM_BAUDRATE; -#else /* Else part of MY_GSM_BAUDRATE */ -uint32_t rate = 0; -#endif /* End of MY_GSM_BAUDRATE */ -#else /* Else part of MY_GATEWAY_TINYGSM */ -static EthernetClient _MQTT_ethClient; -#endif /* End of MY_GATEWAY_TINYGSM */ - -static PubSubClient _MQTT_client(_MQTT_ethClient); -static bool _MQTT_connecting = true; -static bool _MQTT_available = false; -static MyMessage _MQTT_msg; - -bool gatewayTransportSend(MyMessage &message) -{ - if (!_MQTT_client.connected()) { - return false; - } - setIndication(INDICATION_GW_TX); - char *topic = protocolMyMessage2MQTT(MY_MQTT_PUBLISH_TOPIC_PREFIX, message); - GATEWAY_DEBUG(PSTR("GWT:TPS:TOPIC=%s,MSG SENT\n"), topic); -#if defined(MY_MQTT_CLIENT_PUBLISH_RETAIN) - const bool retain = message.getCommand() == C_SET || - (message.getCommand() == C_INTERNAL && message.getType() == I_BATTERY_LEVEL); -#else - const bool retain = false; -#endif /* End of MY_MQTT_CLIENT_PUBLISH_RETAIN */ - return _MQTT_client.publish(topic, message.getString(_convBuffer), retain); -} - -void incomingMQTT(char *topic, uint8_t *payload, unsigned int length) -{ - GATEWAY_DEBUG(PSTR("GWT:IMQ:TOPIC=%s, MSG RECEIVED\n"), topic); - _MQTT_available = protocolMQTT2MyMessage(_MQTT_msg, topic, payload, length); - setIndication(INDICATION_GW_RX); -} - -bool reconnectMQTT(void) -{ - GATEWAY_DEBUG(PSTR("GWT:RMQ:CONNECTING...\n")); - // Attempt to connect - if (_MQTT_client.connect(MY_MQTT_CLIENT_ID, MY_MQTT_USER, MY_MQTT_PASSWORD)) { - GATEWAY_DEBUG(PSTR("GWT:RMQ:OK\n")); - // Send presentation of locally attached sensors (and node if applicable) - presentNode(); - // Once connected, publish subscribe - if (__builtin_constant_p(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX)) { - // to save some memory - _MQTT_client.subscribe(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "/+/+/+/+/+"); - } else { - char inTopic[strlen(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) + strlen("/+/+/+/+/+")]; - (void)strncpy(inTopic, MY_MQTT_SUBSCRIBE_TOPIC_PREFIX, strlen(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) + 1); - (void)strcat(inTopic, "/+/+/+/+/+"); - _MQTT_client.subscribe(inTopic); - } - - return true; - } - delay(1000); - GATEWAY_DEBUG(PSTR("!GWT:RMQ:FAIL\n")); - return false; -} - -bool gatewayTransportConnect(void) -{ -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) - if (WiFi.status() != WL_CONNECTED) { - GATEWAY_DEBUG(PSTR("GWT:TPC:CONNECTING...\n")); - delay(1000); - return false; - } - GATEWAY_DEBUG(PSTR("GWT:TPC:IP=%s\n"), WiFi.localIP().toString().c_str()); -#elif defined(MY_GATEWAY_LINUX) -#if defined(MY_IP_ADDRESS) - _MQTT_ethClient.bind(_MQTT_clientIp); -#endif /* End of MY_IP_ADDRESS */ -#elif defined(MY_GATEWAY_TINYGSM) - GATEWAY_DEBUG(PSTR("GWT:TPC:IP=%s\n"), modem.getLocalIP().c_str()); -#else -#if defined(MY_IP_ADDRESS) - Ethernet.begin(_MQTT_clientMAC, _MQTT_clientIp); -#else /* Else part of MY_IP_ADDRESS */ - // Get IP address from DHCP - if (!Ethernet.begin(_MQTT_clientMAC)) { - GATEWAY_DEBUG(PSTR("!GWT:TPC:DHCP FAIL\n")); - _MQTT_connecting = false; - return false; - } -#endif /* End of MY_IP_ADDRESS */ - GATEWAY_DEBUG(PSTR("GWT:TPC:IP=%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "\n"), - Ethernet.localIP()[0], - Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]); - // give the Ethernet interface a second to initialize - delay(1000); -#endif - return true; -} - -bool gatewayTransportInit(void) -{ - _MQTT_connecting = true; - -#if defined(MY_GATEWAY_TINYGSM) - -#if !defined(MY_GSM_BAUDRATE) - rate = TinyGsmAutoBaud(SerialAT); -#endif /* End of MY_GSM_BAUDRATE */ - - SerialAT.begin(rate); - delay(3000); - - modem.restart(); - -#if defined(MY_GSM_PIN) && !defined(TINY_GSM_MODEM_ESP8266) - modem.simUnlock(MY_GSM_PIN); -#endif /* End of MY_GSM_PIN */ - -#ifndef TINY_GSM_MODEM_ESP8266 - if (!modem.waitForNetwork()) { - GATEWAY_DEBUG(PSTR("!GWT:TIN:ETH FAIL\n")); - while (true); - } - GATEWAY_DEBUG(PSTR("GWT:TIN:ETH OK\n")); - - if (!modem.gprsConnect(MY_GSM_APN, MY_GSM_USR, MY_GSM_PSW)) { - GATEWAY_DEBUG(PSTR("!GWT:TIN:ETH FAIL\n")); - while (true); - } - GATEWAY_DEBUG(PSTR("GWT:TIN:ETH OK\n")); - delay(1000); -#else /* Else part of TINY_GSM_MODEM_ESP8266 */ - if (!modem.networkConnect(MY_GSM_SSID, MY_GSM_PSW)) { - GATEWAY_DEBUG(PSTR("!GWT:TIN:ETH FAIL\n")); - while (true); - } - GATEWAY_DEBUG(PSTR("GWT:TIN:ETH OK\n")); - delay(1000); -#endif /* End of TINY_GSM_MODEM_ESP8266 */ - -#endif /* End of MY_GATEWAY_TINYGSM */ - -#if defined(MY_CONTROLLER_IP_ADDRESS) - _MQTT_client.setServer(_brokerIp, MY_PORT); -#else - _MQTT_client.setServer(MY_CONTROLLER_URL_ADDRESS, MY_PORT); -#endif /* End of MY_CONTROLLER_IP_ADDRESS */ - - _MQTT_client.setCallback(incomingMQTT); - -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) - // Turn off access point - WiFi.mode(WIFI_STA); -#if defined(MY_GATEWAY_ESP8266) - WiFi.hostname(MY_HOSTNAME); -#elif defined(MY_GATEWAY_ESP32) - WiFi.setHostname(MY_HOSTNAME); -#endif -#if defined(MY_IP_ADDRESS) - WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp); -#endif /* End of MY_IP_ADDRESS */ - (void)WiFi.begin(MY_WIFI_SSID, MY_WIFI_PASSWORD, 0, MY_WIFI_BSSID); -#endif - - gatewayTransportConnect(); - - _MQTT_connecting = false; - return true; -} - -bool gatewayTransportAvailable(void) -{ - if (_MQTT_connecting) { - return false; - } -#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32) - if (WiFi.status() != WL_CONNECTED) { -#if defined(MY_GATEWAY_ESP32) - (void)gatewayTransportInit(); -#endif - return false; - } -#endif - if (!_MQTT_client.connected()) { - //reinitialise client - if (gatewayTransportConnect()) { - reconnectMQTT(); - } - return false; - } - _MQTT_client.loop(); - return _MQTT_available; -} - -MyMessage & gatewayTransportReceive(void) -{ - // Return the last parsed message - _MQTT_available = false; - return _MQTT_msg; -} diff --git a/lib/MySensors/core/MyGatewayTransportSerial.cpp b/lib/MySensors/core/MyGatewayTransportSerial.cpp deleted file mode 100644 index dec57b51..00000000 --- a/lib/MySensors/core/MyGatewayTransportSerial.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyConfig.h" -#include "MyProtocol.h" -#include "MyGatewayTransport.h" -#include "MyMessage.h" -#include "MyProtocol.h" - -// global variables -extern MyMessage _msgTmp; - -char _serialInputString[MY_GATEWAY_MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface -uint8_t _serialInputPos; -MyMessage _serialMsg; - -bool gatewayTransportSend(MyMessage &message) -{ - setIndication(INDICATION_GW_TX); - MY_SERIALDEVICE.print(protocolMyMessage2Serial(message)); - // Serial print is always successful - return true; -} - -bool gatewayTransportInit(void) -{ - (void)gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set(MSG_GW_STARTUP_COMPLETE)); - // Send presentation of locally attached sensors (and node if applicable) - presentNode(); - return true; -} - -bool gatewayTransportAvailable(void) -{ - while (MY_SERIALDEVICE.available()) { - // get the new byte: - const char inChar = (char)MY_SERIALDEVICE.read(); - // if the incoming character is a newline, set a flag - // so the main loop can do something about it: - if (_serialInputPos < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { - if (inChar == '\n') { - _serialInputString[_serialInputPos] = 0; - const bool ok = protocolSerial2MyMessage(_serialMsg, _serialInputString); - if (ok) { - setIndication(INDICATION_GW_RX); - } - _serialInputPos = 0; - return ok; - } else { - // add it to the inputString: - _serialInputString[_serialInputPos] = inChar; - _serialInputPos++; - } - } else { - // Incoming message too long. Throw away - _serialInputPos = 0; - } - } - return false; -} - -MyMessage & gatewayTransportReceive(void) -{ - // Return the last parsed message - return _serialMsg; -} diff --git a/lib/MySensors/core/MyHelperFunctions.cpp b/lib/MySensors/core/MyHelperFunctions.cpp deleted file mode 100644 index 7ed22d40..00000000 --- a/lib/MySensors/core/MyHelperFunctions.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHelperFunctions.h" - -static uint8_t convertH2I(const char c) -{ - if (c <= '9') { - return c - '0'; - } else if (c >= 'a') { - return c - 'a' + 10; - } else { - return c - 'A' + 10; - } -} - -static char convertI2H(const uint8_t i) -{ - const uint8_t k = i & 0x0F; - if (k <= 9) { - return '0' + k; - } else { - return 'A' + k - 10; - } -} diff --git a/lib/MySensors/core/MyHelperFunctions.h b/lib/MySensors/core/MyHelperFunctions.h deleted file mode 100644 index ea287da0..00000000 --- a/lib/MySensors/core/MyHelperFunctions.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyHelperFunctions_h -#define MyHelperFunctions_h - -/** -* Single character hex conversion -* @param c hex char -* @return byte representation of the paramter -*/ -static uint8_t convertH2I(const char c) __attribute__((unused)); - -/** -* Lower nibble byte to hex conversion -* @param i byte -* @return hex char representation of the parameter -*/ -static char convertI2H(const uint8_t i) __attribute__((unused)); - - -#endif diff --git a/lib/MySensors/core/MyInclusionMode.cpp b/lib/MySensors/core/MyInclusionMode.cpp deleted file mode 100644 index 8a27e012..00000000 --- a/lib/MySensors/core/MyInclusionMode.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyInclusionMode.h" - -// global variables -extern MyMessage _msgTmp; - -unsigned long _inclusionStartTime; -bool _inclusionMode; - -inline void inclusionInit() -{ - _inclusionMode = false; -#if defined(MY_INCLUSION_BUTTON_FEATURE) - // Setup digital in that triggers inclusion mode - hwPinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT_PULLUP); -#endif -#if defined (MY_INCLUSION_LED_PIN) - // Setup LED pin that indicates inclusion mode - hwPinMode(MY_INCLUSION_LED_PIN, OUTPUT); - hwDigitalWrite(MY_INCLUSION_LED_PIN, LED_OFF); -#endif - -} - - -void inclusionModeSet(bool newMode) -{ - if (newMode != _inclusionMode) { - _inclusionMode = newMode; - // Send back mode change to controller - gatewayTransportSend(buildGw(_msgTmp, I_INCLUSION_MODE).set((uint8_t)(_inclusionMode?1:0))); - if (_inclusionMode) { - _inclusionStartTime = hwMillis(); - } - } -#if defined (MY_INCLUSION_LED_PIN) - hwDigitalWrite(MY_INCLUSION_LED_PIN, _inclusionMode ? LED_ON : LED_OFF); -#endif -} - -inline void inclusionProcess() -{ -#ifdef MY_INCLUSION_BUTTON_FEATURE - if (!_inclusionMode && hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED) { - // Start inclusion mode - inclusionModeSet(true); - } -#endif - - if (_inclusionMode && hwMillis()-_inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { - // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode - inclusionModeSet(false); - } -} diff --git a/lib/MySensors/core/MyInclusionMode.h b/lib/MySensors/core/MyInclusionMode.h deleted file mode 100644 index 4b18e453..00000000 --- a/lib/MySensors/core/MyInclusionMode.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyInclusionMode_h -#define MyInclusionMode_h - -#include "MySensorsCore.h" - - -extern bool gatewayTransportSend(MyMessage &message); - -void inclusionInit(); -void inclusionModeSet(bool newMode); -void inclusionProcess(); - - -#endif diff --git a/lib/MySensors/core/MyIndication.cpp b/lib/MySensors/core/MyIndication.cpp deleted file mode 100644 index 271f93d8..00000000 --- a/lib/MySensors/core/MyIndication.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyIndication.h" -#if defined(MY_DEFAULT_TX_LED_PIN)|| defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) -#include "MyLeds.h" -#endif - -void setIndication( const indication_t ind ) -{ -#if defined(MY_DEFAULT_TX_LED_PIN) - if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) { - ledsBlinkTx(1); - } else -#endif -#if defined(MY_DEFAULT_RX_LED_PIN) - if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) { - ledsBlinkRx(1); - } else -#endif -#if defined(MY_DEFAULT_ERR_LED_PIN) - if (ind > INDICATION_ERR_START) { - // Number of blinks indicates which error occurred. - ledsBlinkErr(ind-INDICATION_ERR_START); - } -#endif - indication(ind); -} - -#if !defined(MY_INDICATION_HANDLER) -void indication(indication_t) -{ - // empty function, resolves AVR-specific GCC optimization bug (<5.5) if handler not used - // see here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77326 -} -#endif diff --git a/lib/MySensors/core/MyIndication.h b/lib/MySensors/core/MyIndication.h deleted file mode 100644 index 04551642..00000000 --- a/lib/MySensors/core/MyIndication.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyIndication_h -#define MyIndication_h - -/** - * Indication type - */ -typedef enum { - INDICATION_TX = 0, //!< Sent a message. - INDICATION_RX, //!< Received a message. - - INDICATION_GW_TX, //!< Gateway transmit message. - INDICATION_GW_RX, //!< Gateway receive message. - - INDICATION_FIND_PARENT, //!< Start finding parent node. - INDICATION_GOT_PARENT, //!< Found parent node. - INDICATION_REQ_NODEID, //!< Request node ID. - INDICATION_GOT_NODEID, //!< Got a node ID. - INDICATION_CHECK_UPLINK, //!< Check uplink - INDICATION_REQ_REGISTRATION, //!< Request node registration. - INDICATION_GOT_REGISTRATION, //!< Got registration response. - INDICATION_REBOOT, //!< Rebooting node. - INDICATION_PRESENT, //!< Presenting node to gateway. - INDICATION_CLEAR_ROUTING, //!< Clear routing table requested. - INDICATION_SLEEP, //!< Node goes to sleep. - INDICATION_WAKEUP, //!< Node just woke from sleep. - INDICATION_FW_UPDATE_START, //!< Start of OTA firmware update process. - INDICATION_FW_UPDATE_RX, //!< Received a piece of firmware data. - INDICATION_FW_UPDATE_RX_ERR, //!< Received wrong piece of firmware data. - - INDICATION_ERR_START = 100, - INDICATION_ERR_HW_INIT, //!< HW initialization error - INDICATION_ERR_TX, //!< Failed to transmit message. - INDICATION_ERR_TRANSPORT_FAILURE, //!< Transport failure. - INDICATION_ERR_INIT_TRANSPORT, //!< MySensors transport hardware (radio) init failure. - INDICATION_ERR_FIND_PARENT, //!< Failed to find parent node. - INDICATION_ERR_GET_NODEID, //!< Failed to receive node ID. - INDICATION_ERR_CHECK_UPLINK, //!< Failed to check uplink - INDICATION_ERR_SIGN, //!< Error signing. - INDICATION_ERR_LENGTH, //!< Invalid message length. - INDICATION_ERR_VERSION, //!< Protocol version mismatch. - INDICATION_ERR_NET_FULL, //!< Network full. All node ID's are taken. - INDICATION_ERR_INIT_GWTRANSPORT, //!< Gateway transport hardware init failure. - INDICATION_ERR_LOCKED, //!< Node is locked. - INDICATION_ERR_FW_FLASH_INIT, //!< Firmware update flash initialisation failure. - INDICATION_ERR_FW_TIMEOUT, //!< Firmware update timeout. - INDICATION_ERR_FW_CHECKSUM, //!< Firmware update checksum mismatch. - INDICATION_ERR_END -} indication_t; - -/** - * Function which is called when something changes about the internal state of MySensors. - * @param ind Event indication of what happened. - */ -void setIndication( const indication_t ind ); - -/** - * Allow user to define their own indication handler. - */ -void indication( const indication_t ); - -#endif diff --git a/lib/MySensors/core/MyLeds.cpp b/lib/MySensors/core/MyLeds.cpp deleted file mode 100644 index b3a4e14b..00000000 --- a/lib/MySensors/core/MyLeds.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyLeds.h" - -#define LED_ON_OFF_RATIO (4) // Power of 2 please -#define LED_PROCESS_INTERVAL_MS (MY_DEFAULT_LED_BLINK_PERIOD/LED_ON_OFF_RATIO) - -// these variables don't need to be volatile, since we are not using interrupts -static uint8_t countRx; -static uint8_t countTx; -static uint8_t countErr; -static unsigned long prevTime; - -inline void ledsInit() -{ - // initialize counters - countRx = 0; - countTx = 0; - countErr = 0; - - // Setup led pins -#if defined(MY_DEFAULT_RX_LED_PIN) - hwPinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); -#endif -#if defined(MY_DEFAULT_TX_LED_PIN) - hwPinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); -#endif -#if defined(MY_DEFAULT_ERR_LED_PIN) - hwPinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); -#endif - prevTime = hwMillis() - - LED_PROCESS_INTERVAL_MS; // Subtract some, to make sure leds gets updated on first run. - ledsProcess(); -} - -void ledsProcess() -{ - // Just return if it is not the time... - if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) { - return; - } - prevTime = hwMillis(); - -#if defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - uint8_t state; -#endif - - // For an On/Off ratio of 4, the pattern repeated will be [on, on, on, off] - // until the counter becomes 0. -#if defined(MY_DEFAULT_RX_LED_PIN) - if (countRx) { - --countRx; - } - state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state); -#endif - -#if defined(MY_DEFAULT_TX_LED_PIN) - if (countTx) { - --countTx; - } - state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state); -#endif - -#if defined(MY_DEFAULT_ERR_LED_PIN) - if (countErr) { - --countErr; - } - state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state); -#endif -} - -void ledsBlinkRx(uint8_t cnt) -{ - if (!countRx) { - countRx = cnt*LED_ON_OFF_RATIO; - } - ledsProcess(); -} - -void ledsBlinkTx(uint8_t cnt) -{ - if(!countTx) { - countTx = cnt*LED_ON_OFF_RATIO; - } - ledsProcess(); -} - -void ledsBlinkErr(uint8_t cnt) -{ - if(!countErr) { - countErr = cnt*LED_ON_OFF_RATIO; - } - ledsProcess(); -} - -bool ledsBlinking() -{ - return countRx || countTx || countErr; -} diff --git a/lib/MySensors/core/MyLeds.h b/lib/MySensors/core/MyLeds.h deleted file mode 100644 index b74c820c..00000000 --- a/lib/MySensors/core/MyLeds.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyLeds_h -#define MyLeds_h - - -#ifdef MY_WITH_LEDS_BLINKING_INVERSE -#define LED_ON 0x1 -#define LED_OFF 0x0 -#else -#define LED_ON 0x0 -#define LED_OFF 0x1 -#endif - -#if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) -#define ledBlinkTx(x,...) ledsBlinkTx(x) -#define ledBlinkRx(x,...) ledsBlinkRx(x) -#define ledBlinkErr(x,...) ledsBlinkErr(x) - -/** - * Blink with LEDs - * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms - */ -void ledsInit(); -void ledsBlinkRx(uint8_t cnt); -void ledsBlinkTx(uint8_t cnt); -void ledsBlinkErr(uint8_t cnt); -void ledsProcess(); // do the actual blinking -/** - * Test if any LED is currently blinking. - * @return true when one or more LEDs are blinking, false otherwise. - */ -bool ledsBlinking(); - -#else -// Remove led functions if feature is disabled -#define ledBlinkTx(x,...) -#define ledBlinkRx(x,...) -#define ledBlinkErr(x,...) -#endif - -#endif diff --git a/lib/MySensors/core/MyMessage.cpp b/lib/MySensors/core/MyMessage.cpp deleted file mode 100644 index b67a0aa5..00000000 --- a/lib/MySensors/core/MyMessage.cpp +++ /dev/null @@ -1,462 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - - -#include "MyMessage.h" -#include "MyHelperFunctions.h" -#include -#include -#include - -MyMessage::MyMessage(void) -{ - this->clear(); -} - -MyMessage::MyMessage(const uint8_t _sensorId, const mysensors_data_t _dataType) -{ - this->clear(); - (void)this->setSensor(_sensorId); - (void)this->setType(static_cast(_dataType)); -} - -void MyMessage::clear(void) -{ - this->last = 0u; - this->sender = 0u; - this->destination = GATEWAY_ADDRESS; // Gateway is default destination - this->version_length = 0u; - this->command_echo_payload = 0u; - this->type = 0u; - this->sensor = 0u; - // clear data buffer - (void)memset((void *)this->data, 0u, sizeof(this->data)); - - // set message protocol version - (void)this->setVersion(); -} - -uint8_t MyMessage::getHeaderSize(void) const -{ - return (uint8_t)HEADER_SIZE; -} - -uint8_t MyMessage::getMaxPayloadSize(void) const -{ - return (uint8_t)MAX_PAYLOAD_SIZE; -} - -uint8_t MyMessage::getExpectedMessageSize(void) const -{ - return this->getHeaderSize() + (this->getSigned() ? this->getMaxPayloadSize() : this->getLength()); -} - -bool MyMessage::isProtocolVersionValid(void) const -{ - return (this->getVersion() == V2_MYS_HEADER_PROTOCOL_VERSION); -} - -uint8_t MyMessage::getType(void) const -{ - return this->type; -} - -MyMessage& MyMessage::setType(const uint8_t messageType) -{ - this->type = messageType; - return *this; -} - -uint8_t MyMessage::getLast(void) const -{ - return this->last; -} - -MyMessage& MyMessage::setLast(const uint8_t lastId) -{ - this->last = lastId; - return *this; -} - -uint8_t MyMessage::getSender(void) const -{ - return this->sender; -} - -MyMessage& MyMessage::setSender(const uint8_t senderId) -{ - this->sender = senderId; - return *this; -} - -uint8_t MyMessage::getSensor(void) const -{ - return this->sensor; -} - -MyMessage& MyMessage::setSensor(const uint8_t sensorId) -{ - this->sensor = sensorId; - return *this; -} - -uint8_t MyMessage::getDestination(void) const -{ - return this->destination; -} - -MyMessage& MyMessage::setDestination(const uint8_t destinationId) -{ - this->destination = destinationId; - return *this; -} - -// TODO: Remove before v3 is released, use isEcho instead -bool MyMessage::isAck(void) const -{ - return this->isEcho(); -} - -bool MyMessage::isEcho(void) const -{ - return (bool)BF_GET(this->command_echo_payload, V2_MYS_HEADER_CEP_ECHO_POS, - V2_MYS_HEADER_CEP_ECHO_SIZE); -} - -MyMessage& MyMessage::setEcho(const bool echo) -{ - BF_SET(this->command_echo_payload, echo, V2_MYS_HEADER_CEP_ECHO_POS, - V2_MYS_HEADER_CEP_ECHO_SIZE); - return *this; -} - -bool MyMessage::getRequestEcho(void) const -{ - return (bool)BF_GET(this->command_echo_payload, V2_MYS_HEADER_CEP_ECHOREQUEST_POS, - V2_MYS_HEADER_CEP_ECHOREQUEST_SIZE); -} - -MyMessage& MyMessage::setRequestEcho(const bool requestEcho) -{ - BF_SET(this->command_echo_payload, requestEcho, V2_MYS_HEADER_CEP_ECHOREQUEST_POS, - V2_MYS_HEADER_CEP_ECHOREQUEST_SIZE); - return *this; -} - -uint8_t MyMessage::getVersion(void) const -{ - return (uint8_t)BF_GET(this->version_length, V2_MYS_HEADER_VSL_VERSION_POS, - V2_MYS_HEADER_VSL_VERSION_SIZE); -} - -MyMessage& MyMessage::setVersion(void) -{ - BF_SET(this->version_length, V2_MYS_HEADER_PROTOCOL_VERSION, V2_MYS_HEADER_VSL_VERSION_POS, - V2_MYS_HEADER_VSL_VERSION_SIZE); - return *this; -} - -mysensors_command_t MyMessage::getCommand(void) const -{ - return static_cast(BF_GET(this->command_echo_payload, - V2_MYS_HEADER_CEP_COMMAND_POS, V2_MYS_HEADER_CEP_COMMAND_SIZE)); -} - -MyMessage& MyMessage::setCommand(const mysensors_command_t command) -{ - BF_SET(this->command_echo_payload, static_cast(command), V2_MYS_HEADER_CEP_COMMAND_POS, - V2_MYS_HEADER_CEP_COMMAND_SIZE); - return *this; -} - -mysensors_payload_t MyMessage::getPayloadType(void) const -{ - return static_cast(BF_GET(this->command_echo_payload, - V2_MYS_HEADER_CEP_PAYLOADTYPE_POS, V2_MYS_HEADER_CEP_PAYLOADTYPE_SIZE)); -} - -MyMessage& MyMessage::setPayloadType(const mysensors_payload_t payloadType) -{ - BF_SET(this->command_echo_payload, static_cast(payloadType), - V2_MYS_HEADER_CEP_PAYLOADTYPE_POS, V2_MYS_HEADER_CEP_PAYLOADTYPE_SIZE); - return *this; -} - -bool MyMessage::getSigned(void) const -{ - return (bool)BF_GET(this->version_length, V2_MYS_HEADER_VSL_SIGNED_POS, - V2_MYS_HEADER_VSL_SIGNED_SIZE); -} - -MyMessage& MyMessage::setSigned(const bool signedFlag) -{ - BF_SET(this->version_length, signedFlag, V2_MYS_HEADER_VSL_SIGNED_POS, - V2_MYS_HEADER_VSL_SIGNED_SIZE); - return *this; -} - -uint8_t MyMessage::getLength(void) const -{ - uint8_t length = BF_GET(this->version_length, V2_MYS_HEADER_VSL_LENGTH_POS, - V2_MYS_HEADER_VSL_LENGTH_SIZE); - // limit length - if (length > MAX_PAYLOAD_SIZE) { - length = MAX_PAYLOAD_SIZE; - } - return length; -} - -MyMessage& MyMessage::setLength(const uint8_t length) -{ - uint8_t finalLength = length; - // limit length - if (finalLength > MAX_PAYLOAD_SIZE) { - finalLength = MAX_PAYLOAD_SIZE; - } - - BF_SET(this->version_length, finalLength, V2_MYS_HEADER_VSL_LENGTH_POS, - V2_MYS_HEADER_VSL_LENGTH_SIZE); - return *this; -} - -/* Getters for payload converted to desired form */ -void* MyMessage::getCustom(void) const -{ - return (void *)this->data; -} - -const char* MyMessage::getString(void) const -{ - if (this->getPayloadType() == P_STRING) { - return this->data; - } else { - return NULL; - } -} - -char* MyMessage::getCustomString(char *buffer) const -{ - if (buffer != NULL) { - for (uint8_t i = 0; i < this->getLength(); i++) { - buffer[i * 2] = convertI2H(this->data[i] >> 4); - buffer[(i * 2) + 1] = convertI2H(this->data[i]); - } - buffer[this->getLength() * 2] = '\0'; - return buffer; - } else { - return NULL; - } -} - -char* MyMessage::getStream(char *buffer) const -{ - if (buffer != NULL) { - if (this->getCommand() == C_STREAM) { - return this->getCustomString(buffer); - } - return buffer; - } else { - return NULL; - } -} - -char* MyMessage::getString(char *buffer) const -{ - if (buffer != NULL) { - const uint8_t payloadType = this->getPayloadType(); - if (payloadType == P_STRING) { - (void)strncpy(buffer, this->data, this->getLength()); - buffer[this->getLength()] = 0; - } else if (payloadType == P_BYTE) { - (void)itoa(bValue, buffer, 10); - } else if (payloadType == P_INT16) { - (void)itoa(iValue, buffer, 10); - } else if (payloadType == P_UINT16) { - (void)utoa(uiValue, buffer, 10); - } else if (payloadType == P_LONG32) { - (void)ltoa(lValue, buffer, 10); - } else if (payloadType == P_ULONG32) { - (void)ultoa(ulValue, buffer, 10); - } else if (payloadType == P_FLOAT32) { - (void)dtostrf(fValue, 2, min(fPrecision, (uint8_t)8u), buffer); - } else if (payloadType == P_CUSTOM) { - return getCustomString(buffer); - } - return buffer; - } else { - return NULL; - } -} - -bool MyMessage::getBool(void) const -{ - return (bool)this->getByte(); -} - -uint8_t MyMessage::getByte(void) const -{ - if (this->getPayloadType() == P_BYTE) { - return (uint8_t)this->data[0]; - } else if (this->getPayloadType() == P_STRING) { - return (uint8_t)atoi(this->data); - } else { - return 0; - } -} - - -float MyMessage::getFloat(void) const -{ - if (this->getPayloadType() == P_FLOAT32) { - return this->fValue; - } else if (this->getPayloadType() == P_STRING) { - return (float)atof(this->data); - } else { - return 0; - } -} - -int32_t MyMessage::getLong(void) const -{ - if (this->getPayloadType() == P_LONG32) { - return this->lValue; - } else if (this->getPayloadType() == P_STRING) { - return (int32_t)atol(this->data); - } else { - return 0; - } -} - -uint32_t MyMessage::getULong(void) const -{ - if (this->getPayloadType() == P_ULONG32) { - return this->ulValue; - } else if (this->getPayloadType() == P_STRING) { - return (uint32_t)atol(this->data); - } else { - return 0; - } -} - -int16_t MyMessage::getInt(void) const -{ - if (this->getPayloadType() == P_INT16) { - return this->iValue; - } else if (this->getPayloadType() == P_STRING) { - return (int16_t)atoi(this->data); - } else { - return 0; - } -} - -uint16_t MyMessage::getUInt(void) const -{ - if (this->getPayloadType() == P_UINT16) { - return this->uiValue; - } else if (this->getPayloadType() == P_STRING) { - return (uint16_t)atoi(this->data); - } else { - return 0; - } -} - -MyMessage& MyMessage::set(const void* value, const size_t _length) -{ - (void)this->setLength((value != NULL) ? _length : 0); - (void)this->setPayloadType(P_CUSTOM); - (void)memcpy((void *)this->data, value, this->getLength()); - return *this; -} - -MyMessage& MyMessage::set(const char* value) -{ - (void)this->setLength((value != NULL) ? strlen(value) : 0); - (void)this->setPayloadType(P_STRING); - (void)strncpy(this->data, value, this->getLength()); - // null terminate string - this->data[this->getLength()] = 0; - return *this; -} - -#if !defined(__linux__) -MyMessage& MyMessage::set(const __FlashStringHelper* value) -{ - (void)this->setLength((value != NULL) ? strlen_P(reinterpret_cast(value)) : 0); - (void)this->setPayloadType(P_STRING); - (void)strncpy_P(this->data, reinterpret_cast(value), this->getLength()); - // null terminate string - this->data[this->getLength()] = 0; - return *this; -} -#endif - - -MyMessage& MyMessage::set(const bool value) -{ - return this->set((uint8_t)value); -} - -MyMessage& MyMessage::set(const uint8_t value) -{ - (void)this->setLength(1u); - (void)this->setPayloadType(P_BYTE); - this->bValue = value; - return *this; -} - -MyMessage& MyMessage::set(const float value, const uint8_t decimals) -{ - (void)this->setLength(5u); // 32 bit float + persi - (void)this->setPayloadType(P_FLOAT32); - this->fValue = value; - this->fPrecision = decimals; - return *this; -} - -MyMessage& MyMessage::set(const uint32_t value) -{ - (void)this->setLength(4u); - (void)this->setPayloadType(P_ULONG32); - this->ulValue = value; - return *this; -} - -MyMessage& MyMessage::set(const int32_t value) -{ - (void)this->setLength(4u); - (void)this->setPayloadType(P_LONG32); - this->lValue = value; - return *this; -} - -MyMessage& MyMessage::set(const uint16_t value) -{ - (void)this->setLength(2u); - (void)this->setPayloadType(P_UINT16); - this->uiValue = value; - return *this; -} - -MyMessage& MyMessage::set(const int16_t value) -{ - (void)this->setLength(2u); - (void)this->setPayloadType(P_INT16); - this->iValue = value; - return *this; -} diff --git a/lib/MySensors/core/MyMessage.h b/lib/MySensors/core/MyMessage.h deleted file mode 100644 index db3627a3..00000000 --- a/lib/MySensors/core/MyMessage.h +++ /dev/null @@ -1,671 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** - * @file MyMessage.h - * - * @brief API and type declarations for MySensors messages - * @defgroup MyMessagegrp MyMessage - * @ingroup publics - * @{ - * - * @brief Here you can find all message types used by the MySensors protocol as well as macros for - * parsing and manipulating messages. - */ -#ifndef MyMessage_h -#define MyMessage_h - -#ifdef __cplusplus -#include -#include -#endif - -#define V2_MYS_HEADER_PROTOCOL_VERSION (2u) //!< Protocol version -#define V2_MYS_HEADER_SIZE (7u) //!< Header size -#define V2_MYS_HEADER_MAX_MESSAGE_SIZE (32u) //!< Max payload size - -#define V2_MYS_HEADER_VSL_VERSION_POS (0) //!< bitfield position version -#define V2_MYS_HEADER_VSL_VERSION_SIZE (2u) //!< size version field -#define V2_MYS_HEADER_VSL_SIGNED_POS (2u) //!< bitfield position signed field -#define V2_MYS_HEADER_VSL_SIGNED_SIZE (1u) //!< size signed field -#define V2_MYS_HEADER_VSL_LENGTH_POS (3u) //!< bitfield position length field -#define V2_MYS_HEADER_VSL_LENGTH_SIZE (5u) //!< size length field - -#define V2_MYS_HEADER_CEP_COMMAND_POS (0) //!< bitfield position command field -#define V2_MYS_HEADER_CEP_COMMAND_SIZE (3u) //!< size command field -#define V2_MYS_HEADER_CEP_ECHOREQUEST_POS (3u) //!< bitfield position echo request field -#define V2_MYS_HEADER_CEP_ECHOREQUEST_SIZE (1u) //!< size echo request field -#define V2_MYS_HEADER_CEP_ECHO_POS (4u) //!< bitfield position echo field -#define V2_MYS_HEADER_CEP_ECHO_SIZE (1u) //!< size echo field -#define V2_MYS_HEADER_CEP_PAYLOADTYPE_POS (5u) //!< bitfield position payload type field -#define V2_MYS_HEADER_CEP_PAYLOADTYPE_SIZE (3u) //!< size payload type field - -#define MAX_MESSAGE_SIZE V2_MYS_HEADER_MAX_MESSAGE_SIZE //!< The maximum size of a message (including header) -#define HEADER_SIZE V2_MYS_HEADER_SIZE //!< The size of the header -#define MAX_PAYLOAD_SIZE (MAX_MESSAGE_SIZE - HEADER_SIZE) //!< The maximum size of a payload depends on #MAX_MESSAGE_SIZE and #HEADER_SIZE - -// deprecated in 3.0.0 -#define MAX_PAYLOAD MAX_PAYLOAD_SIZE //!< \deprecated in 3.0.0 The maximum size of a payload depends on #MAX_MESSAGE_SIZE and #HEADER_SIZE - -/// @brief The command field (message-type) defines the overall properties of a message -typedef enum { - C_PRESENTATION = 0, //!< Sent by a node when they present attached sensors. This is usually done in presentation() at startup. - C_SET = 1, //!< This message is sent from or to a sensor when a sensor value should be updated. - C_REQ = 2, //!< Requests a variable value (usually from an actuator destined for controller). - C_INTERNAL = 3, //!< Internal MySensors messages (also include common messages provided/generated by the library). - C_STREAM = 4, //!< For firmware and other larger chunks of data that need to be divided into pieces. - C_RESERVED_5 = 5, //!< C_RESERVED_5 - C_RESERVED_6 = 6, //!< C_RESERVED_6 - C_INVALID_7 = 7 //!< C_INVALID_7 -} mysensors_command_t; - -#if !DOXYGEN // Hide until we migrate -/// @brief Type of sensor (used when presenting sensors) -typedef enum { - S_DOOR = 0, //!< Door sensor, V_TRIPPED, V_ARMED - S_MOTION = 1, //!< Motion sensor, V_TRIPPED, V_ARMED - S_SMOKE = 2, //!< Smoke sensor, V_TRIPPED, V_ARMED - S_BINARY = 3, //!< Binary light or relay, V_STATUS, V_WATT - S_LIGHT = 3, //!< \deprecated Same as S_BINARY - S_DIMMER = 4, //!< Dimmable light or fan device, V_STATUS (on/off), V_PERCENTAGE (dimmer level 0-100), V_WATT - S_COVER = 5, //!< Blinds or window cover, V_UP, V_DOWN, V_STOP, V_PERCENTAGE (open/close to a percentage) - S_TEMP = 6, //!< Temperature sensor, V_TEMP - S_HUM = 7, //!< Humidity sensor, V_HUM - S_BARO = 8, //!< Barometer sensor, V_PRESSURE, V_FORECAST - S_WIND = 9, //!< Wind sensor, V_WIND, V_GUST - S_RAIN = 10, //!< Rain sensor, V_RAIN, V_RAINRATE - S_UV = 11, //!< Uv sensor, V_UV - S_WEIGHT = 12, //!< Personal scale sensor, V_WEIGHT, V_IMPEDANCE - S_POWER = 13, //!< Power meter, V_WATT, V_KWH, V_VAR, V_VA, V_POWER_FACTOR - S_HEATER = 14, //!< Header device, V_HVAC_SETPOINT_HEAT, V_HVAC_FLOW_STATE, V_TEMP - S_DISTANCE = 15, //!< Distance sensor, V_DISTANCE - S_LIGHT_LEVEL = 16, //!< Light level sensor, V_LIGHT_LEVEL (uncalibrated in percentage), V_LEVEL (light level in lux) - S_ARDUINO_NODE = 17, //!< Used (internally) for presenting a non-repeating Arduino node - S_ARDUINO_REPEATER_NODE = 18, //!< Used (internally) for presenting a repeating Arduino node - S_LOCK = 19, //!< Lock device, V_LOCK_STATUS - S_IR = 20, //!< IR device, V_IR_SEND, V_IR_RECEIVE - S_WATER = 21, //!< Water meter, V_FLOW, V_VOLUME - S_AIR_QUALITY = 22, //!< Air quality sensor, V_LEVEL - S_CUSTOM = 23, //!< Custom sensor - S_DUST = 24, //!< Dust sensor, V_LEVEL - S_SCENE_CONTROLLER = 25, //!< Scene controller device, V_SCENE_ON, V_SCENE_OFF. - S_RGB_LIGHT = 26, //!< RGB light. Send color component data using V_RGB. Also supports V_WATT - S_RGBW_LIGHT = 27, //!< RGB light with an additional White component. Send data using V_RGBW. Also supports V_WATT - S_COLOR_SENSOR = 28, //!< Color sensor, send color information using V_RGB - S_HVAC = 29, //!< Thermostat/HVAC device. V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE, V_TEMP - S_MULTIMETER = 30, //!< Multimeter device, V_VOLTAGE, V_CURRENT, V_IMPEDANCE - S_SPRINKLER = 31, //!< Sprinkler, V_STATUS (turn on/off), V_TRIPPED (if fire detecting device) - S_WATER_LEAK = 32, //!< Water leak sensor, V_TRIPPED, V_ARMED - S_SOUND = 33, //!< Sound sensor, V_TRIPPED, V_ARMED, V_LEVEL (sound level in dB) - S_VIBRATION = 34, //!< Vibration sensor, V_TRIPPED, V_ARMED, V_LEVEL (vibration in Hz) - S_MOISTURE = 35, //!< Moisture sensor, V_TRIPPED, V_ARMED, V_LEVEL (water content or moisture in percentage?) - S_INFO = 36, //!< LCD text device / Simple information device on controller, V_TEXT - S_GAS = 37, //!< Gas meter, V_FLOW, V_VOLUME - S_GPS = 38, //!< GPS Sensor, V_POSITION - S_WATER_QUALITY = 39 //!< V_TEMP, V_PH, V_ORP, V_EC, V_STATUS -} mysensors_sensor_t; - -/// @brief Type of sensor data (for set/req/echo messages) -typedef enum { - V_TEMP = 0, //!< S_TEMP. Temperature S_TEMP, S_HEATER, S_HVAC - V_HUM = 1, //!< S_HUM. Humidity - V_STATUS = 2, //!< S_BINARY, S_DIMMER, S_SPRINKLER, S_HVAC, S_HEATER. Used for setting/reporting binary (on/off) status. 1=on, 0=off - V_LIGHT = 2, //!< \deprecated Same as V_STATUS - V_PERCENTAGE = 3, //!< S_DIMMER. Used for sending a percentage value 0-100 (%). - V_DIMMER = 3, //!< \deprecated Same as V_PERCENTAGE - V_PRESSURE = 4, //!< S_BARO. Atmospheric Pressure - V_FORECAST = 5, //!< S_BARO. Whether forecast. string of "stable", "sunny", "cloudy", "unstable", "thunderstorm" or "unknown" - V_RAIN = 6, //!< S_RAIN. Amount of rain - V_RAINRATE = 7, //!< S_RAIN. Rate of rain - V_WIND = 8, //!< S_WIND. Wind speed - V_GUST = 9, //!< S_WIND. Gust - V_DIRECTION = 10, //!< S_WIND. Wind direction 0-360 (degrees) - V_UV = 11, //!< S_UV. UV light level - V_WEIGHT = 12, //!< S_WEIGHT. Weight(for scales etc) - V_DISTANCE = 13, //!< S_DISTANCE. Distance - V_IMPEDANCE = 14, //!< S_MULTIMETER, S_WEIGHT. Impedance value - V_ARMED = 15, //!< S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER. Armed status of a security sensor. 1 = Armed, 0 = Bypassed - V_TRIPPED = 16, //!< S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER, S_WATER_LEAK, S_SOUND, S_VIBRATION, S_MOISTURE. Tripped status of a security sensor. 1 = Tripped, 0 - V_WATT = 17, //!< S_POWER, S_BINARY, S_DIMMER, S_RGB_LIGHT, S_RGBW_LIGHT. Watt value for power meters - V_KWH = 18, //!< S_POWER. Accumulated number of KWH for a power meter - V_SCENE_ON = 19, //!< S_SCENE_CONTROLLER. Turn on a scene - V_SCENE_OFF = 20, //!< S_SCENE_CONTROLLER. Turn of a scene - V_HVAC_FLOW_STATE = 21, //!< S_HEATER, S_HVAC. HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver") - V_HEATER = 21, //!< \deprecated Same as V_HVAC_FLOW_STATE - V_HVAC_SPEED = 22, //!< S_HVAC, S_HEATER. HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") - V_LIGHT_LEVEL = 23, //!< S_LIGHT_LEVEL. Uncalibrated light level. 0-100%. Use V_LEVEL for light level in lux - V_VAR1 = 24, //!< VAR1 - V_VAR2 = 25, //!< VAR2 - V_VAR3 = 26, //!< VAR3 - V_VAR4 = 27, //!< VAR4 - V_VAR5 = 28, //!< VAR5 - V_UP = 29, //!< S_COVER. Window covering. Up - V_DOWN = 30, //!< S_COVER. Window covering. Down - V_STOP = 31, //!< S_COVER. Window covering. Stop - V_IR_SEND = 32, //!< S_IR. Send out an IR-command - V_IR_RECEIVE = 33, //!< S_IR. This message contains a received IR-command - V_FLOW = 34, //!< S_WATER. Flow of water (in meter) - V_VOLUME = 35, //!< S_WATER. Water volume - V_LOCK_STATUS = 36, //!< S_LOCK. Set or get lock status. 1=Locked, 0=Unlocked - V_LEVEL = 37, //!< S_DUST, S_AIR_QUALITY, S_SOUND (dB), S_VIBRATION (hz), S_LIGHT_LEVEL (lux) - V_VOLTAGE = 38, //!< S_MULTIMETER - V_CURRENT = 39, //!< S_MULTIMETER - V_RGB = 40, //!< S_RGB_LIGHT, S_COLOR_SENSOR. Sent as ASCII hex: RRGGBB (RR=red, GG=green, BB=blue component) - V_RGBW = 41, //!< S_RGBW_LIGHT. Sent as ASCII hex: RRGGBBWW (WW=white component) - V_ID = 42, //!< Used for sending in sensors hardware ids (i.e. OneWire DS1820b). - V_UNIT_PREFIX = 43, //!< Allows sensors to send in a string representing the unit prefix to be displayed in GUI, not parsed by controller! E.g. cm, m, km, inch. - V_HVAC_SETPOINT_COOL = 44, //!< S_HVAC. HVAC cool setpoint (Integer between 0-100) - V_HVAC_SETPOINT_HEAT = 45, //!< S_HEATER, S_HVAC. HVAC/Heater setpoint (Integer between 0-100) - V_HVAC_FLOW_MODE = 46, //!< S_HVAC. Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn") - V_TEXT = 47, //!< S_INFO. Text message to display on LCD or controller device - V_CUSTOM = 48, //!< Custom messages used for controller/inter node specific commands, preferably using S_CUSTOM device type. - V_POSITION = 49, //!< GPS position and altitude. Payload: latitude;longitude;altitude(m). E.g. "55.722526;13.017972;18" - V_IR_RECORD = 50, //!< Record IR codes S_IR for playback - V_PH = 51, //!< S_WATER_QUALITY, water PH - V_ORP = 52, //!< S_WATER_QUALITY, water ORP : redox potential in mV - V_EC = 53, //!< S_WATER_QUALITY, water electric conductivity μS/cm (microSiemens/cm) - V_VAR = 54, //!< S_POWER, Reactive power: volt-ampere reactive (var) - V_VA = 55, //!< S_POWER, Apparent power: volt-ampere (VA) - V_POWER_FACTOR = 56, //!< S_POWER, Ratio of real power to apparent power: floating point value in the range [-1,..,1] -} mysensors_data_t; -#endif - -/// @brief Type of internal messages (for internal messages) -typedef enum { - I_BATTERY_LEVEL = 0, //!< Battery level - I_TIME = 1, //!< Time (request/response) - I_VERSION = 2, //!< Version - I_ID_REQUEST = 3, //!< ID request - I_ID_RESPONSE = 4, //!< ID response - I_INCLUSION_MODE = 5, //!< Inclusion mode - I_CONFIG = 6, //!< Config (request/response) - I_FIND_PARENT_REQUEST = 7, //!< Find parent - I_FIND_PARENT_RESPONSE = 8, //!< Find parent response - I_LOG_MESSAGE = 9, //!< Log message - I_CHILDREN = 10, //!< Children - I_SKETCH_NAME = 11, //!< Sketch name - I_SKETCH_VERSION = 12, //!< Sketch version - I_REBOOT = 13, //!< Reboot request - I_GATEWAY_READY = 14, //!< Gateway ready - I_SIGNING_PRESENTATION = 15, //!< Provides signing related preferences (first byte is preference version) - I_NONCE_REQUEST = 16, //!< Request for a nonce - I_NONCE_RESPONSE = 17, //!< Payload is nonce data - I_HEARTBEAT_REQUEST = 18, //!< Heartbeat request - I_PRESENTATION = 19, //!< Presentation message - I_DISCOVER_REQUEST = 20, //!< Discover request - I_DISCOVER_RESPONSE = 21, //!< Discover response - I_HEARTBEAT_RESPONSE = 22, //!< Heartbeat response - I_LOCKED = 23, //!< Node is locked (reason in string-payload) - I_PING = 24, //!< Ping sent to node, payload incremental hop counter - I_PONG = 25, //!< In return to ping, sent back to sender, payload incremental hop counter - I_REGISTRATION_REQUEST = 26, //!< Register request to GW - I_REGISTRATION_RESPONSE = 27, //!< Register response from GW - I_DEBUG = 28, //!< Debug message - I_SIGNAL_REPORT_REQUEST = 29, //!< Device signal strength request - I_SIGNAL_REPORT_REVERSE = 30, //!< Internal - I_SIGNAL_REPORT_RESPONSE = 31, //!< Device signal strength response (RSSI) - I_PRE_SLEEP_NOTIFICATION = 32, //!< Message sent before node is going to sleep - I_POST_SLEEP_NOTIFICATION = 33 //!< Message sent after node woke up (if enabled) -} mysensors_internal_t; - -/// @brief Type of data stream (for streamed message) -typedef enum { - ST_FIRMWARE_CONFIG_REQUEST = 0, //!< Request new FW, payload contains current FW details - ST_FIRMWARE_CONFIG_RESPONSE = 1, //!< New FW details to initiate OTA FW update - ST_FIRMWARE_REQUEST = 2, //!< Request FW block - ST_FIRMWARE_RESPONSE = 3, //!< Response FW block - ST_SOUND = 4, //!< Sound - ST_IMAGE = 5, //!< Image - ST_FIRMWARE_CONFIRM = 6, //!< Mark running firmware as valid (MyOTAFirmwareUpdateNVM + mcuboot) - ST_FIRMWARE_RESPONSE_RLE = 7, //!< Response FW block with run length encoded data -} mysensors_stream_t; - -/// @brief Type of payload -typedef enum { - P_STRING = 0, //!< Payload type is string - P_BYTE = 1, //!< Payload type is byte - P_INT16 = 2, //!< Payload type is INT16 - P_UINT16 = 3, //!< Payload type is UINT16 - P_LONG32 = 4, //!< Payload type is INT32 - P_ULONG32 = 5, //!< Payload type is UINT32 - P_CUSTOM = 6, //!< Payload type is binary - P_FLOAT32 = 7 //!< Payload type is float32 -} mysensors_payload_t; - - -#ifndef BIT -#define BIT(n) ( 1<<(n) ) //!< Bit indexing macro -#endif -#define BIT_MASK(len) ( BIT(len)-1 ) //!< Create a bitmask of length 'len' -#define BF_MASK(start, len) ( BIT_MASK(len)<<(start) ) //!< Create a bitfield mask of length starting at bit 'start' - -#define BF_PREP(x, start, len) ( ((x)&BIT_MASK(len)) << (start) ) //!< Prepare a bitmask for insertion or combining -#define BF_GET(y, start, len) ( ((y)>>(start)) & BIT_MASK(len) ) //!< Extract a bitfield of length 'len' starting at bit 'start' from 'y' -#define BF_SET(y, x, start, len) ( y= ((y) &~ BF_MASK(start, len)) | BF_PREP(x, start, len) ) //!< Insert a new bitfield value 'x' into 'y' - -// Getters/setters for special bit fields in header -// deprecated in 3.0.0 -#define mSetVersion(_message, _version) _message.setVersion(_version) //!< \deprecated Set version field -#define mGetVersion(_message) _message.getVersion() //!< \deprecated Get version field - -#define mSetSigned(_message, _signed) _message.setSigned(_signed) //!< \deprecated Set signed field -#define mGetSigned(_message) _message.getSigned() //!< \deprecated Get signed field - -#define mSetLength(_message,_length) _message.setLength(_length) //!< \deprecated Set length field -#define mGetLength(_message) _message.getLength() //!< \deprecated Get length field - -#define mSetCommand(_message, _command) _message.setCommand(_command) //!< \deprecated Set command field -#define mGetCommand(_message) _message.getCommand() //!< \deprecated Get command field - -#define mSetRequestEcho(_message, _requestEcho) _message.setRequestEcho(_requestEcho) //!< \deprecated Set echo request field -#define mGetRequestEcho(_message) _message.getRequestEcho() //!< \deprecated Get echo request field - -#define mSetEcho(_message, _echo) _message.setEcho(_echo) //!< \deprecated Set echo field -#define mGetEcho(_message) _message.getEcho() //!< \deprecated Get echo field - -#define mSetPayloadType(_message, _payloadType) _message.setPayloadType(_payloadType) //!< \deprecated Set payload type field -#define mGetPayloadType(_message) _message.getPayloadType() //!< \deprecated Get payload type field - -#if defined(__cplusplus) || defined(DOXYGEN) -/** - * @brief MyMessage is used to create, manipulate, send and read MySensors messages - */ -class MyMessage -{ -private: - char* getCustomString(char *buffer) const; - -public: - - /** - * Default constructor - */ - MyMessage(void); - - /** - * Constructor - * @param sensorId id of the child sensor for this message - * @param dataType - */ - MyMessage(const uint8_t sensorId, const mysensors_data_t dataType); - - /** - * @brief Clear message contents. - */ - void clear(void); - - /** - * If payload is something else than P_STRING you can have the payload value converted - * into string representation by supplying a buffer with the minimum size of - * 2 * MAX_PAYLOAD_SIZE + 1. This is to be able to fit hex-conversion of a full binary payload. - * @param buffer pointer to a buffer that's at least 2 * MAX_PAYLOAD_SIZE + 1 bytes large - */ - char* getStream(char *buffer) const; - - /** - * @brief Copy the payload into the supplied buffer - */ - char* getString(char *buffer) const; - - /** - * @brief Get payload as string - * @return pointer to a char array storing the string - */ - const char* getString(void) const; - - /** - * @brief Get custom payload - * @return pointer to the raw payload - */ - void* getCustom(void) const; - - /** - * @brief Get bool payload - * @return a bool with the value of the payload (true/false) - */ - bool getBool(void) const; - - /** - * @brief Get unsigned 8-bit integer payload - * @return the value of the payload, 0 to 255 - */ - uint8_t getByte(void) const; - - /** - * @brief Get float payload - * @return the floating-point value of the payload - */ - float getFloat(void) const; - - /** - * @brief Get signed 16-bit integer payload - * @return the value of the payload, –32768 to 32767 - */ - int16_t getInt(void) const; - - /** - * @brief Get unsigned 16-bit integer payload - * @return the value of the payload, 0 to 65535 - */ - uint16_t getUInt(void) const; - - /** - * @brief Get signed 32-bit integer payload - * @return the value of the payload, –2147483648 to 2147483647 - */ - int32_t getLong(void) const; - - /** - * @brief Get unsigned 32-bit integer payload - * @return the value of the payload, 0 to 4294967295 - */ - uint32_t getULong(void) const; - - /** - * @brief getHeaderSize - * @return the size of the header - */ - uint8_t getHeaderSize(void) const; - - /** - * @brief getMaxPayloadSize - * @return the max. size of the payload - */ - uint8_t getMaxPayloadSize(void) const; - - /** - * @brief getExpectedMessageSize - * @return the expected message size based on header information - */ - uint8_t getExpectedMessageSize(void) const; - - /** - * @brief isProtocolVersionValid - * @return true if the protocol version is valid - */ - bool isProtocolVersionValid(void) const; - - /** - * @brief Getter for echo request - * @return echo request - */ - bool getRequestEcho(void) const; - - /** - * @brief Setter for echo request - * @param requestEcho - */ - MyMessage& setRequestEcho(const bool requestEcho); - - /** - * @brief Getter for version - * @return version - */ - uint8_t getVersion(void) const; - - /** - * @brief Setter for version - */ - MyMessage& setVersion(void); - - /** - * @brief Getter for length - * @return length - */ - uint8_t getLength(void) const; - - /** - * @brief Setter for length - * @param length - */ - MyMessage& setLength(const uint8_t length); - - /** - * @brief Getter for command type - * @return #mysensors_command_t - */ - mysensors_command_t getCommand(void) const; - - /** - * @brief Setter for command type - * @param command - */ - MyMessage& setCommand(const mysensors_command_t command); - - /** - * @brief Getter for payload type - * @return payload type - */ - mysensors_payload_t getPayloadType(void) const; - - /** - * @brief Setter for payload type - * @param payloadType - */ - MyMessage& setPayloadType(const mysensors_payload_t payloadType); - - /** - * @brief Getter for sign field - * @return sign field - */ - bool getSigned(void) const; - - /** - * @brief Setter for sign field - * @param signedFlag - */ - MyMessage& setSigned(const bool signedFlag); - - /** - * \deprecated use isEcho() - * @brief Getter for echo-flag. - * @return true if this is an echoed message - */ - bool isAck(void) const; - - /** - * @brief Getter for echo-flag. - * @return true if this is an echoed message - */ - bool isEcho(void) const; - - /** - * @brief Setter for echo-flag. - * @param echo true if this an echo message - */ - MyMessage& setEcho(const bool echo); - - /** - * @brief Get message type - * @return messageType - */ - uint8_t getType(void) const; - - /** - * @brief Set message type - * @param messageType - */ - MyMessage& setType(const uint8_t messageType); - - /** - * @brief Get last ID - * @return lastId - */ - uint8_t getLast(void) const; - - /** - * @brief Set last ID - * @param lastId - */ - MyMessage& setLast(const uint8_t lastId); - - /** - * @brief Get sender ID - * @return sender - */ - uint8_t getSender(void) const; - - /** - * @brief Set sender ID - * @param senderId - */ - MyMessage& setSender(const uint8_t senderId); - - /** - * @brief Get sensor ID of message - * @return sensorId - */ - uint8_t getSensor(void) const; - - /** - * @brief Set which child sensor this message belongs to - * @param sensorId - */ - MyMessage& setSensor(const uint8_t sensorId); - - /** - * @brief Get destination - * @return destinationId - */ - uint8_t getDestination(void) const; - - /** - * @brief Set final destination node id for this message - * @param destinationId - */ - MyMessage& setDestination(const uint8_t destinationId); - - /** - * @brief Set entire payload - * @param payload pointer to the buffer where the payload is stored - * @param length of the payload - */ - MyMessage& set(const void* payload, const size_t length); - - /** - * @brief Set payload to character array - * @param value pointer to the character array. The array must be null-terminated. - */ - MyMessage& set(const char* value); -#if !defined(__linux__) - /** - * @brief Set payload to character array from flash - * @param value pointer to the character array. The array must be null-terminated. - */ - MyMessage& set(const __FlashStringHelper* value); -#endif - - /** - * @brief Set payload to decimal number - * @param value float - * @param decimals number of decimals to include - */ - MyMessage& set(const float value, const uint8_t decimals); - - /** - * @brief Set payload to bool value - * @param value true or false - */ - MyMessage& set(const bool value); - - /** - * @brief Set payload to unsigned 8-bit integer value - * @param value (0 to 255) - */ - MyMessage& set(const uint8_t value); - - /** - * @brief Set payload to unsigned 32-bit integer value - * @param value (0 to 4294967295) - */ - MyMessage& set(const uint32_t value); - - /** - * @brief Set payload to signed 32-bit integer value - * @param value (–2147483648 to 2147483647) - */ - MyMessage& set(const int32_t value); - - /** - * @brief Set payload to unsigned 16-bit integer value - * @param value (0 to 65535) - */ - MyMessage& set(const uint16_t value); - - /** - * @brief Set payload to signed 16-bit integer value - * @param value (–32768 to 32767) - */ - MyMessage& set(const int16_t value); - -#else - -typedef union { - struct { - -#endif - uint8_t last; //!< 8 bit - Id of last node this message passed - uint8_t sender; //!< 8 bit - Id of sender node (origin) - uint8_t destination; //!< 8 bit - Id of destination node - - /** - * 2 bit - Protocol version
- * 1 bit - Signed flag
- * 5 bit - Length of payload - */ - uint8_t version_length; - - /** - * 3 bit - Command type
- * 1 bit - Request an echo - Indicator that receiver should echo the message back to the sender
- * 1 bit - Is echo message - Indicator that this is the echoed message
- * 3 bit - Payload data type - */ - uint8_t command_echo_payload; - - uint8_t type; //!< 8 bit - Type varies depending on command - uint8_t sensor; //!< 8 bit - Id of sensor that this message concerns. - - /* - * Each message can transfer a payload. We add one extra byte for string - * terminator \0 to be "printable" this is not transferred OTA - * This union is used to simplify the construction of the binary data types transferred. - */ - union { - uint8_t bValue; //!< unsigned byte value (8-bit) - uint16_t uiValue; //!< unsigned integer value (16-bit) - int16_t iValue; //!< signed integer value (16-bit) - uint32_t ulValue; //!< unsigned long value (32-bit) - int32_t lValue; //!< signed long value (32-bit) - struct { //!< Float messages - float fValue; - uint8_t fPrecision; //!< Number of decimals when serializing - }; - char data[MAX_PAYLOAD_SIZE + 1]; //!< Buffer for raw payload data - } __attribute__((packed)); //!< Doxygen will complain without this comment -#if defined(__cplusplus) || defined(DOXYGEN) -} __attribute__((packed)); -#else -}; -uint8_t array[HEADER_SIZE + MAX_PAYLOAD_SIZE + 1]; //!< buffer for entire message -} __attribute__((packed)) MyMessage; -#endif - -#endif -/** @}*/ diff --git a/lib/MySensors/core/MyOTAFirmwareUpdate.cpp b/lib/MySensors/core/MyOTAFirmwareUpdate.cpp deleted file mode 100644 index b1dbccc6..00000000 --- a/lib/MySensors/core/MyOTAFirmwareUpdate.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyOTAFirmwareUpdate.h" - -// global variables -extern MyMessage _msg; -extern MyMessage _msgTmp; - -// local variables -#ifdef MY_OTA_USE_I2C_EEPROM -I2CEeprom _flash(MY_OTA_I2C_ADDR); -#elif !defined(MCUBOOT_PRESENT) -SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID); -#endif - -// Map flash functions -#ifndef MCUBOOT_PRESENT -#define _flash_initialize() _flash.initialize() -#define _flash_readByte(addr) _flash.readByte(addr) -#define _flash_writeBytes( dstaddr, data, size) _flash.writeBytes( dstaddr, data, size) -#define _flash_blockErase32K(num) _flash.blockErase32K(num) -#define _flash_busy() _flash.busy() -#else -#define _flash_initialize() true -#define _flash_readByte(addr) (*((uint8_t *)(addr))) -#define _flash_blockErase32K(num) Flash.erase((uint32_t *)FLASH_AREA_IMAGE_1_OFFSET_0, FLASH_AREA_IMAGE_1_SIZE_0) -#define _flash_busy() false -#endif - -LOCAL nodeFirmwareConfig_t _nodeFirmwareConfig; -LOCAL bool _firmwareUpdateOngoing = false; -LOCAL uint32_t _firmwareLastRequest; -LOCAL uint16_t _firmwareBlock; -LOCAL uint8_t _firmwareRetry; -LOCAL bool _firmwareResponse(uint16_t block, uint8_t *data); - -LOCAL void readFirmwareSettings(void) -{ - hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, - sizeof(nodeFirmwareConfig_t)); -} - -LOCAL void firmwareOTAUpdateRequest(void) -{ - const uint32_t enterMS = hwMillis(); - if (_firmwareUpdateOngoing && (enterMS - _firmwareLastRequest > MY_OTA_RETRY_DELAY)) { - if (!_firmwareRetry) { - setIndication(INDICATION_ERR_FW_TIMEOUT); - OTA_DEBUG(PSTR("!OTA:FRQ:FW UPD FAIL\n")); // fw update failed - // Give up. We have requested MY_OTA_RETRY times without any packet in return. - _firmwareUpdateOngoing = false; - return; - } - _firmwareRetry--; - _firmwareLastRequest = enterMS; - // Time to (re-)request firmware block from controller - requestFirmwareBlock_t firmwareRequest; - firmwareRequest.type = _nodeFirmwareConfig.type; - firmwareRequest.version = _nodeFirmwareConfig.version; - firmwareRequest.block = (_firmwareBlock - 1); - OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04" PRIX16 ",V=%04" PRIX16 ",B=%04" PRIX16 "\n"), - _nodeFirmwareConfig.type, - _nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, - false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t))); - } -} - -LOCAL bool firmwareOTAUpdateProcess(void) -{ - if (_msg.getType() == ST_FIRMWARE_CONFIG_RESPONSE) { - if(_firmwareUpdateOngoing) { - OTA_DEBUG(PSTR("!OTA:FWP:UPDO\n")); // FW config response received, FW update already ongoing - return true; - } - nodeFirmwareConfig_t *firmwareConfigResponse = (nodeFirmwareConfig_t *)_msg.data; - // compare with current node configuration, if they differ, start FW fetch process - if (memcmp(&_nodeFirmwareConfig, firmwareConfigResponse, sizeof(nodeFirmwareConfig_t))) { - setIndication(INDICATION_FW_UPDATE_START); - OTA_DEBUG(PSTR("OTA:FWP:UPDATE\n")); // FW update initiated - // copy new FW config - (void)memcpy(&_nodeFirmwareConfig, firmwareConfigResponse, sizeof(nodeFirmwareConfig_t)); - // Init flash - if (!_flash_initialize()) { - setIndication(INDICATION_ERR_FW_FLASH_INIT); - OTA_DEBUG(PSTR("!OTA:FWP:FLASH INIT FAIL\n")); // failed to initialise flash - _firmwareUpdateOngoing = false; - } else { - // erase lower 32K -> max flash size for ATMEGA328 - _flash_blockErase32K(0); - // wait until flash erased - while ( _flash_busy() ) {} - _firmwareBlock = _nodeFirmwareConfig.blocks; - _firmwareUpdateOngoing = true; - // reset flags - _firmwareRetry = MY_OTA_RETRY + 1; - _firmwareLastRequest = 0; - } - return true; - } - OTA_DEBUG(PSTR("OTA:FWP:UPDATE SKIPPED\n")); // FW update skipped, no newer version available - } else if (_msg.getType() == ST_FIRMWARE_RESPONSE) { - // extract FW block - replyFirmwareBlock_t *firmwareResponse = (replyFirmwareBlock_t *)_msg.data; - // Proceed firmware data - return _firmwareResponse(firmwareResponse->block, firmwareResponse->data); -#ifdef FIRMWARE_PROTOCOL_31 - } else if (_msg.getType() == ST_FIRMWARE_RESPONSE_RLE) { - // RLE encoded block - // extract FW block - replyFirmwareBlockRLE_t *firmwareResponse = (replyFirmwareBlockRLE_t *)_msg.data; - uint8_t data[FIRMWARE_BLOCK_SIZE]; - for (uint8_t i=0; idata; - } - while ((_firmwareBlock) && (firmwareResponse->number_of_blocks)) { - _firmwareResponse(firmwareResponse->block, data); - firmwareResponse->number_of_blocks--; - firmwareResponse->block--; - } - return true; -#endif - } else { -#ifdef MCUBOOT_PRESENT - if (_msg.getType() == ST_FIRMWARE_CONFIRM) { - if (*(uint16_t *)MCUBOOT_IMAGE_0_MAGIC_ADDR == ((uint16_t)MCUBOOT_IMAGE_MAGIC)) { - if (*(uint8_t *)(MCUBOOT_IMAGE_0_IMG_OK_ADDR) != MCUBOOT_IMAGE_0_IMG_OK_BYTE) { - // Calculate data word to write - uint32_t *img_ok_base_addr = (uint32_t *)(MCUBOOT_IMAGE_0_IMG_OK_ADDR & ~3); // align word wise - uint32_t img_ok_data = *img_ok_base_addr; - // Set copy of MCUBOOT_IMAGE_0_IMG_OK_ADDR to MCUBOOT_IMAGE_0_IMG_OK_BYTE (0x01) - uint8_t *img_ok_array = (uint8_t *)&img_ok_data; - *(img_ok_array + (MCUBOOT_IMAGE_0_IMG_OK_ADDR % 4)) = MCUBOOT_IMAGE_0_IMG_OK_BYTE; - // Write word back - Flash.write(img_ok_base_addr, img_ok_data); - } - OTA_DEBUG(PSTR("!OTA:FWP:IMAGE CONFIRMED\n")); - } else { - OTA_DEBUG(PSTR("!OTA:FWP:INVALID MCUBOOT MAGIC\n")); - } - } -#endif - } - return false; -} - -LOCAL void presentBootloaderInformation(void) -{ - requestFirmwareConfig_t *requestFirmwareConfig = (requestFirmwareConfig_t *)_msgTmp.data; - _msgTmp.setLength(sizeof(requestFirmwareConfig_t)); - _msgTmp.setCommand(C_STREAM); - _msgTmp.setPayloadType(P_CUSTOM); - // copy node settings to reqFWConfig - (void)memcpy(requestFirmwareConfig, &_nodeFirmwareConfig, sizeof(nodeFirmwareConfig_t)); - // add bootloader information - requestFirmwareConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; -#ifdef FIRMWARE_PROTOCOL_31 - requestFirmwareConfig->blockSize = FIRMWARE_BLOCK_SIZE; -#ifndef MCUBOOT_PRESENT - requestFirmwareConfig->img_commited = 0x2; - requestFirmwareConfig->img_revision = 0x00; - requestFirmwareConfig->img_build_num = 0x00; -#else - requestFirmwareConfig->img_commited = *((uint8_t*)(MCUBOOT_IMAGE_0_IMG_OK_ADDR)); - requestFirmwareConfig->img_revision = *((uint16_t*)(MCUBOOT_IMAGE_0_IMG_REVISION_ADDR)); - requestFirmwareConfig->img_build_num = *((uint16_t*)(MCUBOOT_IMAGE_0_IMG_BUILD_NUM_ADDR)); -#endif -#endif - _firmwareUpdateOngoing = false; - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, - ST_FIRMWARE_CONFIG_REQUEST, false)); -} - -LOCAL bool isFirmwareUpdateOngoing(void) -{ - return _firmwareUpdateOngoing; -} -// do a crc16 on the whole received firmware -LOCAL bool transportIsValidFirmware(void) -{ - // init crc - uint16_t crc = ~0; - for (uint32_t i = 0; i < _nodeFirmwareConfig.blocks * FIRMWARE_BLOCK_SIZE; ++i) { - crc ^= _flash_readByte(i + FIRMWARE_START_OFFSET); - for (int8_t j = 0; j < 8; ++j) { - if (crc & 1) { - crc = (crc >> 1) ^ 0xA001; - } else { - crc = (crc >> 1); - } - } - } - OTA_DEBUG(PSTR("OTA:CRC:B=%04" PRIX16 ",C=%04" PRIX16 ",F=%04" PRIX16 "\n"), - _nodeFirmwareConfig.blocks,crc, - _nodeFirmwareConfig.crc); - return crc == _nodeFirmwareConfig.crc; -} - -LOCAL bool _firmwareResponse(uint16_t block, uint8_t *data) -{ - if (_firmwareUpdateOngoing) { - OTA_DEBUG(PSTR("OTA:FWP:RECV B=%04" PRIX16 "\n"), block); // received FW block - if (block != _firmwareBlock - 1) { - OTA_DEBUG(PSTR("!OTA:FWP:WRONG FWB\n")); // received FW block - // wrong firmware block received - setIndication(INDICATION_FW_UPDATE_RX_ERR); - // no further processing required - return true; - } - setIndication(INDICATION_FW_UPDATE_RX); - // Save block to flash -#ifdef MCUBOOT_PRESENT - uint32_t addr = ((size_t)(((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE)) + (size_t)( - FIRMWARE_START_OFFSET)); - if (addr>2); - } -#else - _flash_writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, - data, FIRMWARE_BLOCK_SIZE); -#endif - // wait until flash written - while (_flash_busy()) {} -#ifdef OTA_EXTRA_FLASH_DEBUG - { - char prbuf[8]; - uint32_t addr = ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET; - OTA_DEBUG(PSTR("OTA:FWP:FL DUMP ")); - sprintf_P(prbuf,PSTR("%04" PRIX16 ":"), (uint16_t)addr); - MY_SERIALDEVICE.print(prbuf); - for(uint8_t i=0; i> 8), (uint8_t)(firmwareSize & 0xff),':'}; - _flash_writeBytes(0, OTAbuffer, FIRMWARE_START_OFFSET); - // wait until flash ready - while (_flash_busy()) {} -#endif - hwReboot(); - } else { - setIndication(INDICATION_ERR_FW_CHECKSUM); - OTA_DEBUG(PSTR("!OTA:FWP:CRC FAIL\n")); - } - } - // reset flags - _firmwareRetry = MY_OTA_RETRY + 1; - _firmwareLastRequest = 0; - } else { - OTA_DEBUG(PSTR("!OTA:FWP:NO UPDATE\n")); - } - return true; -} diff --git a/lib/MySensors/core/MyOTAFirmwareUpdate.h b/lib/MySensors/core/MyOTAFirmwareUpdate.h deleted file mode 100644 index 880291b5..00000000 --- a/lib/MySensors/core/MyOTAFirmwareUpdate.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** -* @file MyOTAFirmwareUpdate.h -* -* @defgroup MyOTAFirmwaregrp MyOTAFirmwareUpdate -* @ingroup internals -* @{ -* -* MyOTAFirmwareUpdate-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE -* - [!] Exclamation mark is prepended in case of error or warning -* - SYSTEM: -* - OTA messages emitted by MyOTAFirmwareUpdate -* - SUB SYSTEMS: -* - OTA:FRQ from @ref firmwareOTAUpdateRequest() -* - OTA:FWP from @ref firmwareOTAUpdateProcess() -* -* MyOTAFirmwareUpdate debug log messages: -* -* |E| SYS | SUB | Message | Comment -* |-|-----|-----|-----------------------------|---------------------------------------------------------------------------- -* | | OTA | FWP | UPDATE | FW update initiated -* |!| OTA | FWP | UPDO | FW config response received, FW update already ongoing -* |!| OTA | FWP | FLASH INIT FAIL | Failed to initialise flash -* | | OTA | FWP | UPDATE SKIPPED | FW update skipped, no newer version available -* | | OTA | FWP | RECV B=%04X | Received FW block (B) -* |!| OTA | FWP | WRONG FWB | Wrong FW block received -* | | OTA | FWP | FW END | FW received, proceed to CRC verification -* | | OTA | FWP | CRC OK | FW CRC verification OK -* |!| OTA | FWP | CRC FAIL | FW CRC verification failed -* | | OTA | FRQ | FW REQ,T=%04X,V=%04X,B=%04X | Request FW update, FW type (T), version (V), block (B) -* |!| OTA | FRQ | FW UPD FAIL | FW update failed -* | | OTA | CRC | B=%04X,C=%04X,F=%04X | FW CRC verification. FW blocks (B), calculated CRC (C), FW CRC (F) -* -* -* @brief API declaration for MyOTAFirmwareUpdate -*/ - - -#ifndef MyOTAFirmwareUpdate_h -#define MyOTAFirmwareUpdate_h - -#include "MySensorsCore.h" -#ifdef MCUBOOT_PRESENT -#include "generated_dts_board.h" -#define FIRMWARE_PROTOCOL_31 -#endif - -#define LOCAL static //!< static - -#if MAX_PAYLOAD_SIZE >= 22 -#define FIRMWARE_BLOCK_SIZE (16u) //!< Size of each firmware block -#else -#define FIRMWARE_BLOCK_SIZE (8u) //!< Size of each firmware block -#ifndef FIRMWARE_PROTOCOL_31 -#define FIRMWARE_PROTOCOL_31 -#endif -#endif -#ifndef MY_OTA_RETRY -#define MY_OTA_RETRY (5u) //!< Number of times to request a fw block before giving up -#endif -#ifndef MY_OTA_RETRY_DELAY -#define MY_OTA_RETRY_DELAY (500u) //!< Number of milliseconds before re-requesting a FW block -#endif -#ifndef MCUBOOT_PRESENT -#define FIRMWARE_START_OFFSET (10u) //!< Start offset for firmware in flash (DualOptiboot wants to keeps a signature first) -#else -#define FIRMWARE_START_OFFSET (FLASH_AREA_IMAGE_1_OFFSET_0) //!< Use offset from generated_dts_board.h (mcuboot) -#endif - -#define MY_OTA_BOOTLOADER_MAJOR_VERSION (3u) //!< Bootloader version major -#ifdef FIRMWARE_PROTOCOL_31 -#define MY_OTA_BOOTLOADER_MINOR_VERSION (1u) //!< Bootloader version minor -#else -#define MY_OTA_BOOTLOADER_MINOR_VERSION (0u) //!< Bootloader version minor -#endif -#define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION) //!< Bootloader version - -#if defined(MY_DEBUG_VERBOSE_OTA_UPDATE) -#define OTA_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< debug -//#define OTA_EXTRA_FLASH_DEBUG //!< Dumps flash after each FW block -#else -#define OTA_DEBUG(x,...) //!< debug NULL -#endif - -#if defined(DOXYGEN) && !defined(FIRMWARE_PROTOCOL_31) -/** - * @brief Enabled FOTA 3.1 protocol extensions - * - * Supports smaller FIRMWARE_BLOCK_SIZE, RLE and NVM for nRF5 with mcuboot. The - * extension is enabled per default when mcuboot is present or full FIRMWARE_BLOCK_SIZE - * exeeds MAX_PAYLOAD_SIZE. - */ -#define FIRMWARE_PROTOCOL_31 -#endif - -/** -* @brief FW config structure, stored in eeprom -*/ -typedef struct { - uint16_t type; //!< Type of config - uint16_t version; //!< Version of config - uint16_t blocks; //!< Number of blocks - uint16_t crc; //!< CRC of block data -} __attribute__((packed)) nodeFirmwareConfig_t; - -/** -* @brief FW config request structure -*/ -typedef struct { - uint16_t type; //!< Type of config - uint16_t version; //!< Version of config - uint16_t blocks; //!< Number of blocks - uint16_t crc; //!< CRC of block data - uint16_t BLVersion; //!< Bootloader version -#ifdef FIRMWARE_PROTOCOL_31 - uint8_t blockSize; //!< Blocksize, when protocol version >= 3.1 is reported. Otherwhise the blocksize is 16 - uint8_t img_commited; //!< mcuboot image_ok attribute commited firmware=0x01(mcuboot)|0x02(DualOptiboot), when protocol version >= 3.1 is reported - uint16_t img_revision; //!< mcuboot revision attribute, when protocol version >= 3.1 is reported - uint32_t img_build_num; //!< mcuboot build_num attribute, when protocol version >= 3.1 is reported -#endif -} __attribute__((packed)) requestFirmwareConfig_t; - -/** -* @brief FW block request structure -*/ -typedef struct { - uint16_t type; //!< Type of config - uint16_t version; //!< Version of config - uint16_t block; //!< Block index -} __attribute__((packed)) requestFirmwareBlock_t; - -/** -* @brief FW block reply structure -*/ -typedef struct { - uint16_t type; //!< Type of config - uint16_t version; //!< Version of config - uint16_t block; //!< Block index - uint8_t data[FIRMWARE_BLOCK_SIZE]; //!< Block data -} __attribute__((packed)) replyFirmwareBlock_t; - -/** -* @brief FW block reply structure (RLE) -*/ -typedef struct { - uint16_t type; //!< Type of config - uint16_t version; //!< Version of config - uint16_t block; //!< Block index - uint16_t number_of_blocks; //!< Number of blocks to fill with data - uint8_t data; //!< Block data -} __attribute__((packed)) replyFirmwareBlockRLE_t; - -/** - * @brief Read firmware settings from EEPROM - * - * Current firmware settings (type, version, crc, blocks) are read into _fc - */ -LOCAL void readFirmwareSettings(void); -/** - * @brief Handle OTA FW update requests - */ -LOCAL void firmwareOTAUpdateRequest(void); -/** - * @brief Handle OTA FW update responses - * - * This function handles incoming OTA FW packets and stores them to external flash (Sensebender) - */ -LOCAL bool firmwareOTAUpdateProcess(void); -/** - * @brief Validate uploaded FW CRC - * - * This function verifies if uploaded FW CRC is valid - */ -LOCAL bool transportIsValidFirmware(void); -/** - * @brief Present bootloader/FW information upon startup - */ -LOCAL void presentBootloaderInformation(void); - -#endif - -/** @}*/ diff --git a/lib/MySensors/core/MyOTALogging.cpp b/lib/MySensors/core/MyOTALogging.cpp deleted file mode 100644 index 381969d4..00000000 --- a/lib/MySensors/core/MyOTALogging.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ -#include "MyOTALogging.h" - -#ifdef MY_OTA_LOG_SENDER_FEATURE -// global variables -static bool inOTALog = false; - -void OTALog(uint8_t logNode, const bool requestEcho, const char *fmt, ... ) -{ - // Avoid recursion - if (inOTALog==true) { - return; - } - inOTALog = true; - - MyMessage msg(NODE_SENSOR_ID, V_CUSTOM); - char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; - va_list args; - - // create message - va_start (args, fmt ); - int n = vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); - va_end (args); - - // Check number of chars - if (n<1) { - // Nothing to send - inOTALog = false; - return; - } - - // Add \n to the end of string - if (n>(int)(sizeof(fmtBuffer)-2)) { - // String is truncated - n = sizeof(fmtBuffer)-2; - } - - // add LF if not set - if (fmtBuffer[n-1]!='\n') { - fmtBuffer[n++]='\n'; - fmtBuffer[n++]=0; - } - - // Configure message - msg.setSender(getNodeId()); - msg.setDestination(logNode); - msg.setCommand(C_INTERNAL); - msg.setType(I_LOG_MESSAGE); - msg.setRequestEcho(requestEcho); - - // Send package - for (int pos = 0; pos < n; pos += MAX_PAYLOAD_SIZE) { - uint8_t length = strlen(&fmtBuffer[pos]); - if (length > MAX_PAYLOAD_SIZE) { - length = MAX_PAYLOAD_SIZE; - } - (void)_sendRoute(msg.set((char*)&fmtBuffer[pos])); - } - inOTALog = false; -} -#endif - - -#ifdef MY_OTA_LOG_RECEIVER_FEATURE -// Global variables -char OTALogfmtBuffer[MY_SERIAL_OUTPUT_SIZE]; -int OTALogfmtBufferPos = 0; -uint8_t OTALogBufferNode = BROADCAST_ADDRESS; -uint8_t OTALogBufferSensor = 0; - -void OTALogPrintPrefix() -{ - char prefix[37]; - // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) - snprintf_P(prefix, sizeof(prefix), - PSTR("%" PRId8 ";%" PRId8 ";%" PRId8 ";0;%" PRId8 ";%" PRIu32 " "), - OTALogBufferNode, OTALogBufferSensor, C_INTERNAL, I_LOG_MESSAGE, hwMillis()); - MY_SERIALDEVICE.print(prefix); -} - -void OTALogFlushBuffer() -{ - OTALogfmtBuffer[0] = 0; - OTALogfmtBufferPos = 0; - OTALogBufferNode = BROADCAST_ADDRESS; -} - -inline void OTALogPrint(const MyMessage &message) -{ - // Ignore log messages via broadcast - if (message.destination == BROADCAST_ADDRESS) { - return; - } - - // FLush buffer, when node id changes - if ((OTALogBufferNode!=BROADCAST_ADDRESS) && ((OTALogBufferNode != message.getSender()) || - (OTALogBufferSensor != message.getSensor()))) { - OTALogPrintPrefix(); - MY_SERIALDEVICE.print(OTALogfmtBuffer); - MY_SERIALDEVICE.println("..."); - OTALogFlushBuffer(); - } - - // Add data to buffer - const char *str = message.getString(); - strncpy(&OTALogfmtBuffer[OTALogfmtBufferPos], str, - sizeof(OTALogfmtBuffer)-OTALogfmtBufferPos); - OTALogfmtBufferPos += strlen(str); - - // Store node ID and sensor ID - OTALogBufferNode = message.getSender(); - OTALogBufferSensor = message.getSensor(); - - // Print out buffered lines ending with \n - char *EOLpos; - while (EOLpos = strchr(OTALogfmtBuffer,'\n'), EOLpos != NULL) { - // Add end of string - EOLpos[0]=0; - // Print out line - OTALogPrintPrefix(); - MY_SERIALDEVICE.println(OTALogfmtBuffer); - // Check if more content in buffer - int lenAfterEOL = (size_t)&OTALogfmtBuffer[OTALogfmtBufferPos]-(size_t)EOLpos-2; - if (lenAfterEOL>0) { - // More lines, move string to the beginning of the buffer - strcpy((char*)&OTALogfmtBuffer[0], (char*)&EOLpos[1]); - // calculate OTALogfmtBufferPos - OTALogfmtBufferPos -= (size_t)EOLpos-(size_t)&OTALogfmtBuffer[0]+2; - // Security check - if ((OTALogfmtBufferPos<=0) || (OTALogfmtBufferPos>=(int)sizeof(OTALogfmtBuffer))) { - MY_SERIALDEVICE.print("Sec:"); - MY_SERIALDEVICE.println(OTALogfmtBufferPos); - OTALogFlushBuffer(); - } - } else { - // End of message, prepare new one - OTALogFlushBuffer(); - } - } -} -#endif diff --git a/lib/MySensors/core/MyOTALogging.h b/lib/MySensors/core/MyOTALogging.h deleted file mode 100644 index 2bb4fe34..00000000 --- a/lib/MySensors/core/MyOTALogging.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** - * @file MyOTALogging.h - * - * @brief API declaration for MyOTALogging - * @defgroup MyOTALogginggrp MyOTALogging - * @ingroup internals - * @{ - * - * @brief Enables ending and receiving debug messages over the air. - */ -#ifndef MyOTALogging_h -#define MyOTALogging_h - -#include "MySensorsCore.h" -#include "MyTransport.h" - -/** - * @brief Send a log message to a node - * - * If MY_OTA_LOG_RECEIVER_FEATURE is enabled on the destination node, the given - * message is printed to the serial port. You have to define MY_OTA_LOG_SENDER_FEATURE - * or MY_DEBUG_OTA to enable the OTALog() function. - * - * Output format of each line: - * Node ID;CHILD_NODE_ID;C_INTERNAL;I_LOG_MESSAGE;hwMillis() MESSAGE - * - * You will see the hwMillis() of the receiving node. After each \n character, a - * new debug message line starts. Incomplete messages are ending with '...' - * - * @param logNode Destination node ID - * @param echo Enable or disable echo flag - * @param fmt printf format string - * @param ... arguments - */ -void OTALog(uint8_t logNode, bool echo, const char *fmt, ... ); - -/** - * @brief Handles output of OTA log or debug messages - * - * This function is used by MyTransport.cpp - * - * Output format of each line: - * Node ID;CHILD_NODE_ID;C_INTERNAL;I_LOG_MESSAGE;hwMillis() MESSAGE - * - * You will see the hwMillis() of the receiving node. After each \n character, a - * new debug message line starts. Incomplete messages are ending with '...' - * - * @param message Message buffer to use. - */ -inline void OTALogPrint(const MyMessage &message); - -#endif /* MyOTALogging_h */ - -/** @}*/ diff --git a/lib/MySensors/core/MyPrivateConfig.h.sample b/lib/MySensors/core/MyPrivateConfig.h.sample deleted file mode 100644 index 17351771..00000000 --- a/lib/MySensors/core/MyPrivateConfig.h.sample +++ /dev/null @@ -1,61 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ -/* - * This file contains settings that for various reasons are unsuitable to store in git - * Rename it by removing the .sample extension and place it in the sketch folder and include - * it in the sketch: - * #include "MyPrivateConfig.h" - * Make sure to include it before - * #include - * Then adapt the contents to your personal preference. - */ - -#ifndef MyPrivateConfig_h -#define MyPrivateConfig_h - -/********************************** -* Node identification Settings -***********************************/ -//#define MY_NODE_ID 1 - -/********************************** -* Message Signing Settings -***********************************/ -// Pin used for random generation in soft signing (do not connect anything to this when enabled) -#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 // A7 - - -// Enable node whitelisting -//#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} - -/********************************** -* nRF24L01 Driver Defaults -***********************************/ -// Enables RF24 encryption (all nodes and gateway must have this enabled) -//#define MY_RF24_ENABLE_ENCRYPTION - -/********************************** -* RFM69 Driver Defaults -***********************************/ -// Default network id. Use the same for all nodes that will talk to each other -#define MY_RFM69_NETWORKID 100 - -// Enable this for encryption of packets -//#define MY_RFM69_ENABLE_ENCRYPTION - -#endif diff --git a/lib/MySensors/core/MyProtocol.cpp b/lib/MySensors/core/MyProtocol.cpp deleted file mode 100644 index 86805e1e..00000000 --- a/lib/MySensors/core/MyProtocol.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyConfig.h" -#include "MyTransport.h" -#include "MyProtocol.h" -#include "MyHelperFunctions.h" -#include - -char _fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH]; -char _convBuffer[MAX_PAYLOAD_SIZE * 2 + 1]; - -bool protocolSerial2MyMessage(MyMessage &message, char *inputString) -{ - char *str, *p; - uint8_t index = 0; - mysensors_command_t command = C_INVALID_7; - message.setSender(GATEWAY_ADDRESS); - message.setLast(GATEWAY_ADDRESS); - message.setEcho(false); - - // Extract command data coming on serial line - for (str = strtok_r(inputString, ";", &p); // split using semicolon - str && index < 5; // loop while str is not null an max 4 times - str = strtok_r(NULL, ";", &p), index++ // get subsequent tokens - ) { - switch (index) { - case 0: // Radio id (destination) - message.setDestination(atoi(str)); - break; - case 1: // Child id - message.setSensor(atoi(str)); - break; - case 2: // Message type - command = static_cast(atoi(str)); - message.setCommand(command); - break; - case 3: // Should we request echo from destination? - message.setRequestEcho(atoi(str) ? 1 : 0); - break; - case 4: // Data type - message.setType(atoi(str)); - break; - } - } - // payload - if (str == NULL) { - // no payload, set default value - message.set((uint8_t)0); - } else if (command == C_STREAM) { - // stream payload - uint8_t bvalue[MAX_PAYLOAD_SIZE]; - uint8_t blen = 0; - while (*str) { - uint8_t val; - val = convertH2I(*str++) << 4; - val += convertH2I(*str++); - bvalue[blen] = val; - blen++; - } - message.set(bvalue, blen); - } else { - // regular payload - char *value = str; - // Remove trailing carriage return and newline character (if it exists) - const uint8_t lastCharacter = strlen(value) - 1; - if (value[lastCharacter] == '\r' || value[lastCharacter] == '\n') { - value[lastCharacter] = '\0'; - } - message.set(value); - } - return (index == 5); -} - -char *protocolMyMessage2Serial(MyMessage &message) -{ - (void)snprintf_P(_fmtBuffer, (uint8_t)MY_GATEWAY_MAX_SEND_LENGTH, - PSTR("%" PRIu8 ";%" PRIu8 ";%" PRIu8 ";%" PRIu8 ";%" PRIu8 ";%s\n"), message.getSender(), - message.getSensor(), message.getCommand(), message.isEcho(), message.getType(), - message.getString(_convBuffer)); - return _fmtBuffer; -} - -char *protocolMyMessage2MQTT(const char *prefix, MyMessage &message) -{ - (void)snprintf_P(_fmtBuffer, (uint8_t)MY_GATEWAY_MAX_SEND_LENGTH, - PSTR("%s/%" PRIu8 "/%" PRIu8 "/%" PRIu8 "/%" PRIu8 "/%" PRIu8 ""), prefix, - message.getSender(), message.getSensor(), message.getCommand(), message.isEcho(), - message.getType()); - return _fmtBuffer; -} - - -bool protocolMQTT2MyMessage(MyMessage &message, char *topic, uint8_t *payload, - const unsigned int length) -{ - char *str, *p; - uint8_t index = 0; - message.setSender(GATEWAY_ADDRESS); - message.setLast(GATEWAY_ADDRESS); - message.setEcho(false); - for (str = strtok_r(topic + strlen(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) + 1, "/", &p); - str && index < 5; - str = strtok_r(NULL, "/", &p), index++ - ) { - switch (index) { - case 0: - // Node id - message.setDestination(atoi(str)); - break; - case 1: - // Sensor id - message.setSensor(atoi(str)); - break; - case 2: { - // Command type - const mysensors_command_t command = static_cast(atoi(str)); - message.setCommand(command); - // Add payload - if (command == C_STREAM) { - uint8_t bvalue[MAX_PAYLOAD_SIZE]; - uint8_t blen = 0; - while (*payload) { - uint8_t val; - val = convertH2I(*payload++) << 4; - val += convertH2I(*payload++); - bvalue[blen] = val; - blen++; - } - message.set(bvalue, blen); - } else { - // terminate string - char *value = (char *)payload; - value[length] = '\0'; - message.set((const char*)payload); - } - break; - } - case 3: - // Echo flag - message.setRequestEcho(atoi(str) ? 1 : 0); - break; - case 4: - // Sub type - message.setType(atoi(str)); - break; - } - } - // Return true if input valid - return (index == 5); -} diff --git a/lib/MySensors/core/MyProtocol.h b/lib/MySensors/core/MyProtocol.h deleted file mode 100644 index 6d50faf4..00000000 --- a/lib/MySensors/core/MyProtocol.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyProtocol_h -#define MyProtocol_h - -#include "MySensorsCore.h" - -// parse(message, inputString) -// parse a string into a message element -// returns true if successfully parsed the input string -bool protocolSerial2MyMessage(MyMessage &message, char *inputString); - -// Format MyMessage to the protocol representation -char *protocolMyMessage2Serial(MyMessage &message); - -#endif diff --git a/lib/MySensors/core/MySensorsCore.cpp b/lib/MySensors/core/MySensorsCore.cpp deleted file mode 100644 index 22bbf91a..00000000 --- a/lib/MySensors/core/MySensorsCore.cpp +++ /dev/null @@ -1,833 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MySensorsCore.h" - -// debug output -#if defined(MY_DEBUG_VERBOSE_CORE) -#define CORE_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< debug -#else -#define CORE_DEBUG(x,...) //!< debug NULL -#endif - -// message buffers -MyMessage _msg; // Buffer for incoming messages -MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among others) - -// core configuration -static coreConfig_t _coreConfig; - -#if defined(MY_DEBUG_VERBOSE_CORE) -static uint8_t waitLock = 0; -static uint8_t processLock = 0; -#endif - -#if defined(DEBUG_OUTPUT_ENABLED) -char _convBuf[MAX_PAYLOAD_SIZE * 2 + 1]; -#endif - -// Callback for transport=ok transition -void _callbackTransportReady(void) -{ - if (!_coreConfig.presentationSent) { -#if !defined(MY_GATEWAY_FEATURE) // GW calls presentNode() when client connected - presentNode(); -#endif - _registerNode(); - _coreConfig.presentationSent = true; - } -} - -void _process(void) -{ -#if defined(MY_DEBUG_VERBOSE_CORE) - if (processLock) { - CORE_DEBUG(PSTR("!MCO:PRO:RC=%" PRIu8 "\n"), processLock); // recursive call detected - } - processLock++; -#endif - doYield(); - -#if defined(MY_INCLUSION_MODE_FEATURE) - inclusionProcess(); -#endif - -#if defined(MY_GATEWAY_FEATURE) - gatewayTransportProcess(); -#endif - -#if defined(MY_SENSOR_NETWORK) - transportProcess(); -#endif - -#if defined(__linux__) - // To avoid high cpu usage - usleep(10000); // 10ms -#endif -#if defined(MY_DEBUG_VERBOSE_CORE) - processLock--; -#endif -} - -void _infiniteLoop(void) -{ -#if defined(__linux__) - exit(1); -#else - while(1) { - doYield(); - } -#endif -} - -void _begin(void) -{ -#if defined(MY_CORE_ONLY) - // initialize HW and run setup if present - (void)hwInit(); - if (setup) { - setup(); - } - return; -#endif - // reset wdt - hwWatchdogReset(); - - if (preHwInit) { - preHwInit(); - } - - const bool hwInitResult = hwInit(); - -#if !defined(MY_SPLASH_SCREEN_DISABLED) && !defined(MY_GATEWAY_FEATURE) - displaySplashScreen(); -#endif - -#if defined(F_CPU) - CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",FQ=%" PRIu16 ",REL=%" - PRIu8 ",VER=" - MYSENSORS_LIBRARY_VERSION "\n"), (uint16_t)(F_CPU/1000000UL), - MYSENSORS_LIBRARY_VERSION_PRERELEASE_NUMBER); -#else - CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",FQ=NA,REL=%" - PRIu8 ",VER=" - MYSENSORS_LIBRARY_VERSION "\n"), MYSENSORS_LIBRARY_VERSION_PRERELEASE_NUMBER); -#endif - if (!hwInitResult) { - CORE_DEBUG(PSTR("!MCO:BGN:HW ERR\n")); - setIndication(INDICATION_ERR_HW_INIT); - _infiniteLoop(); - } - - // set defaults - _coreConfig.presentationSent = false; - - // Call sketch before() (if defined) - if (before) { - CORE_DEBUG(PSTR("MCO:BGN:BFR\n")); // before callback - before(); - } - -#if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - ledsInit(); -#endif - - signerInit(); - - // Read latest received controller configuration from EEPROM - // Note: _coreConfig.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default) - hwReadConfigBlock((void *)&_coreConfig.controllerConfig, (void *)EEPROM_CONTROLLER_CONFIG_ADDRESS, - sizeof(controllerConfig_t)); - -#if defined(MY_OTA_FIRMWARE_FEATURE) - // Read firmware config from EEPROM, i.e. type, version, CRC, blocks - readFirmwareSettings(); -#endif - -#if defined(MY_SENSOR_NETWORK) - // Save static parent ID in eeprom (used by bootloader) - hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, MY_PARENT_NODE_ID); - // Initialise transport layer - transportInitialise(); - // Register transport=ready callback - transportRegisterReadyCallback(_callbackTransportReady); - // wait until transport is ready - (void)transportWaitUntilReady(MY_TRANSPORT_WAIT_READY_MS); -#endif - - _checkNodeLock(); - -#if defined(MY_GATEWAY_FEATURE) -#if defined(MY_INCLUSION_BUTTON_FEATURE) - inclusionInit(); -#endif - - // initialise the transport driver - if (!gatewayTransportInit()) { - setIndication(INDICATION_ERR_INIT_GWTRANSPORT); - CORE_DEBUG(PSTR("!MCO:BGN:TSP FAIL\n")); - // Nothing more we can do - _infiniteLoop(); - } -#endif - - // Call sketch setup() (if defined) - if (setup) { - CORE_DEBUG(PSTR("MCO:BGN:STP\n")); // setup callback - setup(); - } -#if defined(MY_SENSOR_NETWORK) - CORE_DEBUG(PSTR("MCO:BGN:INIT OK,TSP=%" PRIu8 "\n"), isTransportReady() && - transportHALSanityCheck()); -#else - // no sensor network defined, call presentation & registration - _callbackTransportReady(); - CORE_DEBUG(PSTR("MCO:BGN:INIT OK,TSP=NA\n")); -#endif - // reset wdt before handing over to loop - hwWatchdogReset(); -} - - -void _registerNode(void) -{ -#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) - CORE_DEBUG(PSTR("MCO:REG:REQ\n")); // registration request - setIndication(INDICATION_REQ_REGISTRATION); - _coreConfig.nodeRegistered = MY_REGISTRATION_DEFAULT; - uint8_t counter = MY_REGISTRATION_RETRIES; - // only proceed if register response received or retries exceeded - do { - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_REGISTRATION_REQUEST).set(MY_CORE_VERSION)); - } while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--); -#else - _coreConfig.nodeRegistered = true; - CORE_DEBUG(PSTR("MCO:REG:NOT NEEDED\n")); -#endif -} - -void presentNode(void) -{ - setIndication(INDICATION_PRESENT); - // Present node and request config -#if defined(MY_GATEWAY_FEATURE) - // Send presentation for this gateway device -#if defined(MY_REPEATER_FEATURE) - (void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); -#else - (void)present(NODE_SENSOR_ID, S_ARDUINO_NODE); -#endif -#else - -#if defined(MY_OTA_FIRMWARE_FEATURE) - presentBootloaderInformation(); -#endif - - // Send signing preferences for this node to the GW - signerPresentation(_msgTmp, GATEWAY_ADDRESS); - - // Send presentation for this radio node -#if defined(MY_REPEATER_FEATURE) - (void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); -#else - (void)present(NODE_SENSOR_ID, S_ARDUINO_NODE); -#endif - - // Send a configuration exchange request to controller - // Node sends parent node. Controller answers with latest node configuration - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_CONFIG).set(getParentNodeId())); - - // Wait configuration reply. - (void)wait(2000, C_INTERNAL, I_CONFIG); - -#endif - - if (presentation) { - presentation(); - } -} - - -uint8_t getNodeId(void) -{ - uint8_t result; -#if defined(MY_GATEWAY_FEATURE) - result = GATEWAY_ADDRESS; -#elif defined(MY_SENSOR_NETWORK) - result = transportGetNodeId(); -#else - result = VALUE_NOT_DEFINED; -#endif - return result; -} - -uint8_t getParentNodeId(void) -{ - uint8_t result; -#if defined(MY_GATEWAY_FEATURE) - result = VALUE_NOT_DEFINED; // GW doesn't have a parent -#elif defined(MY_SENSOR_NETWORK) - result = transportGetParentNodeId(); -#else - result = VALUE_NOT_DEFINED; -#endif - return result; -} - -uint8_t getDistanceGW(void) -{ - uint8_t result; -#if defined(MY_GATEWAY_FEATURE) - result = 0; -#elif defined(MY_SENSOR_NETWORK) - result = transportGetDistanceGW(); -#else - result = VALUE_NOT_DEFINED; -#endif - return result; -} - -controllerConfig_t getControllerConfig(void) -{ - return _coreConfig.controllerConfig; -} - - -bool _sendRoute(MyMessage &message) -{ -#if defined(MY_CORE_ONLY) - (void)message; -#endif -#if defined(MY_GATEWAY_FEATURE) - if (message.getDestination() == getNodeId()) { - // This is a message sent from a sensor attached on the gateway node. - // Pass it directly to the gateway transport layer. - return gatewayTransportSend(message); - } -#endif -#if defined(MY_SENSOR_NETWORK) - return transportSendRoute(message); -#else - return false; -#endif -} - -bool send(MyMessage &message, const bool requestEcho) -{ - message.setSender(getNodeId()); - message.setCommand(C_SET); - message.setRequestEcho(requestEcho); - -#if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) - if (_coreConfig.nodeRegistered) { - return _sendRoute(message); - } else { - CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered - return false; - } -#else - return _sendRoute(message); -#endif -} - -bool sendBatteryLevel(const uint8_t value, const bool requestEcho) -{ - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, - requestEcho).set(value)); -} - -bool sendHeartbeat(const bool requestEcho) -{ -#if defined(MY_SENSOR_NETWORK) - const uint32_t heartbeat = transportGetHeartbeat(); - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, - requestEcho).set(heartbeat)); -#elif defined(MY_GATEWAY_FEATURE) - const uint32_t heartbeat = hwMillis(); - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, - requestEcho).set(heartbeat)); -#else - (void)requestEcho; - return false; -#endif -} - - - -bool present(const uint8_t childSensorId, const mysensors_sensor_t sensorType, - const char *description, - const bool requestEcho) -{ - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, - static_cast(sensorType), - requestEcho).set(childSensorId == NODE_SENSOR_ID ? MYSENSORS_LIBRARY_VERSION : description)); -} - -#if !defined(__linux__) -bool present(const uint8_t childSensorId, const mysensors_sensor_t sensorType, - const __FlashStringHelper *description, - const bool requestEcho) -{ - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, - static_cast(sensorType), - requestEcho).set(childSensorId == NODE_SENSOR_ID ? F(" MYSENSORS_LIBRARY_VERSION "): description)); -} -#endif - - -bool sendSketchInfo(const char *name, const char *version, const bool requestEcho) -{ - bool result = true; - if (name) { - result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, - requestEcho).set(name)); - } - if (version) { - result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, - requestEcho).set(version)); - } - return result; -} - -#if !defined(__linux__) -bool sendSketchInfo(const __FlashStringHelper *name, const __FlashStringHelper *version, - const bool requestEcho) -{ - bool result = true; - if (name) { - result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, - requestEcho).set(name)); - } - if (version) { - result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, - requestEcho).set(version)); - } - return result; -} -#endif - -bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination) -{ - return _sendRoute(build(_msgTmp, destination, childSensorId, C_REQ, variableType).set("")); -} - -bool requestTime(const bool requestEcho) -{ - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, - requestEcho).set("")); -} - -// Message delivered through _msg -bool _processInternalCoreMessage(void) -{ - const uint8_t type = _msg.getType(); - if (_msg.getSender() == GATEWAY_ADDRESS) { - if (type == I_REBOOT) { -#if !defined(MY_DISABLE_REMOTE_RESET) - setIndication(INDICATION_REBOOT); - // WDT fuse should be enabled - hwReboot(); -#endif - } else if (type == I_REGISTRATION_RESPONSE) { -#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) - _coreConfig.nodeRegistered = _msg.getBool(); - setIndication(INDICATION_GOT_REGISTRATION); - CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%" PRIu8 "\n"), _coreConfig.nodeRegistered); // node registration -#endif - } else if (type == I_CONFIG) { - // Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed - _coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 || - _msg.data[0] == 'M'; // metric if null terminated or M - hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, - sizeof(controllerConfig_t)); - } else if (type == I_PRESENTATION) { - // Re-send node presentation to controller - presentNode(); - } else if (type == I_HEARTBEAT_REQUEST) { - (void)sendHeartbeat(); - } else if (type == I_VERSION) { -#if !defined(MY_GATEWAY_FEATURE) - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_VERSION).set(MYSENSORS_LIBRARY_VERSION_INT)); -#endif - } else if (type == I_TIME) { - // Deliver time to callback - if (receiveTime) { - receiveTime(_msg.getULong()); - } - } else if (type == I_CHILDREN) { - if (_msg.data[0] == 'C') { -#if defined(MY_REPEATER_FEATURE) && defined(MY_SENSOR_NETWORK) - // Clears child relay data for this node - setIndication(INDICATION_CLEAR_ROUTING); - transportClearRoutingTable(); - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN).set("OK")); -#endif - } - } else if (type == I_DEBUG) { -#if defined(MY_SPECIAL_DEBUG) - const char debug_msg = _msg.data[0]; - if (debug_msg == 'R') { // routing table -#if defined(MY_REPEATER_FEATURE) && defined(MY_SENSOR_NETWORK) - transportReportRoutingTable(); -#endif - } else if (debug_msg == 'V') { // CPU voltage - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_DEBUG).set(hwCPUVoltage())); - } else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_DEBUG).set(hwCPUFrequency())); - } else if (debug_msg == 'M') { // free memory - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_DEBUG).set(hwFreeMem())); - } else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set("OK")); - for (uint16_t i = EEPROM_START; i= MY_CORE_MIN_VERSION); -#else - // auto registration if version compatible - approveRegistration = true; -#endif - -#if (F_CPU>16*1000000ul) - // delay for fast GW and slow nodes - delay(5); -#endif - (void)_sendRoute(build(_msgTmp, _msg.getSender(), NODE_SENSOR_ID, C_INTERNAL, - I_REGISTRATION_RESPONSE).set(approveRegistration)); -#else - return false; // processing of this request via controller -#endif -#endif - } else { - return false; // further processing required - } - } - return true; // if not GW or no further processing required -} - - -void saveState(const uint8_t pos, const uint8_t value) -{ - hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value); -} -uint8_t loadState(const uint8_t pos) -{ - return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos); -} - - -void wait(const uint32_t waitingMS) -{ -#if defined(MY_DEBUG_VERBOSE_CORE) - if (waitLock) { - CORE_DEBUG(PSTR("!MCO:WAI:RC=%" PRIu8 "\n"), waitLock); // recursive call detected - } - waitLock++; -#endif - const uint32_t enteringMS = hwMillis(); - while (hwMillis() - enteringMS < waitingMS) { - _process(); - } -#if defined(MY_DEBUG_VERBOSE_CORE) - waitLock--; -#endif -} - -bool wait(const uint32_t waitingMS, const mysensors_command_t cmd) -{ -#if defined(MY_DEBUG_VERBOSE_CORE) - if (waitLock) { - CORE_DEBUG(PSTR("!MCO:WAI:RC=%" PRIu8 "\n"), waitLock); // recursive call detected - } - waitLock++; -#endif - const uint32_t enteringMS = hwMillis(); - // invalidate cmd - //_msg.setCommand(!cmd); - _msg.setCommand(C_INVALID_7); - bool expectedResponse = false; - while ((hwMillis() - enteringMS < waitingMS) && !expectedResponse) { - _process(); - expectedResponse = (_msg.getCommand() == cmd); - } -#if defined(MY_DEBUG_VERBOSE_CORE) - waitLock--; -#endif - return expectedResponse; -} - -bool wait(const uint32_t waitingMS, const mysensors_command_t cmd, const uint8_t msgType) -{ -#if defined(MY_DEBUG_VERBOSE_CORE) - if (waitLock) { - CORE_DEBUG(PSTR("!MCO:WAI:RC=%" PRIu8 "\n"), waitLock); // recursive call detected - } - waitLock++; -#endif - const uint32_t enteringMS = hwMillis(); - // invalidate cmd - //_msg.setCommand(!cmd); - _msg.setCommand(C_INVALID_7); - bool expectedResponse = false; - while ( (hwMillis() - enteringMS < waitingMS) && !expectedResponse ) { - _process(); - expectedResponse = (_msg.getCommand() == cmd && _msg.getType() == msgType); - } -#if defined(MY_DEBUG_VERBOSE_CORE) - waitLock--; -#endif - return expectedResponse; -} - -void doYield(void) -{ - hwWatchdogReset(); - yield(); -#if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - ledsProcess(); -#endif -} - -int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1, - const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2) -{ - CORE_DEBUG(PSTR("MCO:SLP:MS=%" PRIu32 ",SMS=%" PRIu8 ",I1=%" PRIu8 ",M1=%" PRIu8 ",I2=%" PRIu8 - ",M2=%" PRIu8 "\n"), sleepingMS, smartSleep, - interrupt1, mode1, interrupt2, mode2); - // repeater feature: sleeping not possible -#if defined(MY_REPEATER_FEATURE) - (void)smartSleep; - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - - CORE_DEBUG(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled - wait(sleepingMS); - return MY_SLEEP_NOT_POSSIBLE; -#else - uint32_t sleepingTimeMS = sleepingMS; -#if defined(MY_SENSOR_NETWORK) - // Do not sleep if transport not ready - if (!isTransportReady()) { - CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready - const uint32_t sleepEnterMS = hwMillis(); - uint32_t sleepDeltaMS = 0; - while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && - (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) { - _process(); - sleepDeltaMS = hwMillis() - sleepEnterMS; - } - // sleep remainder - if (sleepDeltaMS < sleepingTimeMS) { - sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time - CORE_DEBUG(PSTR("MCO:SLP:MS=%" PRIu32 "\n"), sleepingTimeMS); - } else { - // no sleeping time left - return MY_SLEEP_NOT_POSSIBLE; - } - } - // OTA FW feature: do not sleep if FW update ongoing -#if defined(MY_OTA_FIRMWARE_FEATURE) - while (isFirmwareUpdateOngoing() && sleepingTimeMS) { - CORE_DEBUG(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing - wait(1000ul); - sleepingTimeMS = sleepingTimeMS >= 1000ul ? sleepingTimeMS - 1000ul : 1000ul; - } -#endif // MY_OTA_FIRMWARE_FEATURE - if (smartSleep) { - // sleeping time left? - if (sleepingTimeMS > 0 && sleepingTimeMS < ((uint32_t)MY_SMART_SLEEP_WAIT_DURATION_MS)) { - wait(sleepingMS); - CORE_DEBUG(PSTR("!MCO:SLP:NTL\n")); // sleeping not possible, no time left - return MY_SLEEP_NOT_POSSIBLE; - } - // notify controller about going to sleep, payload indicates smartsleep waiting time in MS - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_PRE_SLEEP_NOTIFICATION).set((uint32_t)MY_SMART_SLEEP_WAIT_DURATION_MS)); - wait(MY_SMART_SLEEP_WAIT_DURATION_MS); // listen for incoming messages -#if defined(MY_OTA_FIRMWARE_FEATURE) - // check if during smart sleep waiting period a FOTA request was received - if (isFirmwareUpdateOngoing()) { - CORE_DEBUG(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing - return MY_SLEEP_NOT_POSSIBLE; - } -#endif // MY_OTA_FIRMWARE_FEATURE - } -#else - (void)smartSleep; -#endif // MY_SENSOR_NETWORK - -#if defined(MY_SENSOR_NETWORK) - transportDisable(); -#endif - setIndication(INDICATION_SLEEP); - -#if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - // Wait until leds finish their blinking pattern - while (ledsBlinking()) { - doYield(); - } -#endif - - int8_t result = MY_SLEEP_NOT_POSSIBLE; // default - if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) { - // both IRQs - result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS); - } else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) { - // one IRQ - result = hwSleep(interrupt1, mode1, sleepingTimeMS); - } else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) { - // no IRQ - result = hwSleep(sleepingTimeMS); - } - setIndication(INDICATION_WAKEUP); - CORE_DEBUG(PSTR("MCO:SLP:WUP=%" PRIi8 "\n"), result); // sleep wake-up -#if defined(MY_SENSOR_NETWORK) - transportReInitialise(); -#endif - if (smartSleep) { - // notify controller about waking up, payload indicates sleeping time in MS - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_POST_SLEEP_NOTIFICATION).set(sleepingTimeMS)); - } - return result; -#endif -} - -// sleep functions -int8_t sleep(const uint32_t sleepingMS, const bool smartSleep) -{ - return _sleep(sleepingMS, smartSleep); -} - -int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS, - const bool smartSleep) -{ - return _sleep(sleepingMS, smartSleep, interrupt, mode); -} - -int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep) -{ - return _sleep(sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2); -} - -// deprecated smartSleep() functions -int8_t smartSleep(const uint32_t sleepingMS) -{ - // compatibility - return _sleep(sleepingMS, true); -} - -int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS) -{ - // compatibility - return _sleep(sleepingMS, true, interrupt, mode); -} - -int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, const uint32_t sleepingMS) -{ - // compatibility - return _sleep(sleepingMS, true, interrupt1, mode1, interrupt2, mode2); -} - -uint32_t getSleepRemaining(void) -{ - return hwGetSleepRemaining(); -} - - -void _nodeLock(const char *str) -{ -#ifdef MY_NODE_LOCK_FEATURE - // Make sure EEPROM is updated to locked status - hwWriteConfig(EEPROM_NODE_LOCK_COUNTER_ADDRESS, 0); - while (1) { - setIndication(INDICATION_ERR_LOCKED); - CORE_DEBUG(PSTR("MCO:NLK:NODE LOCKED. TO UNLOCK, GND PIN %" PRIu8 " AND RESET\n"), - MY_NODE_UNLOCK_PIN); - doYield(); - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID,C_INTERNAL, I_LOCKED).set(str)); -#if defined(MY_SENSOR_NETWORK) - transportSleep(); - CORE_DEBUG(PSTR("MCO:NLK:TSL\n")); // sleep transport -#endif - setIndication(INDICATION_SLEEP); - (void)hwSleep((uint32_t)1000*60*30); // Sleep for 30 min before resending LOCKED message - setIndication(INDICATION_WAKEUP); - } -#else - (void)str; -#endif -} - -void _checkNodeLock(void) -{ -#ifdef MY_NODE_LOCK_FEATURE - // Check if node has been locked down - if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER_ADDRESS) == 0) { - // Node is locked, check if unlock pin is asserted, else hang the node - hwPinMode(MY_NODE_UNLOCK_PIN, INPUT_PULLUP); - // Make a short delay so we are sure any large external nets are fully pulled - uint32_t enter = hwMillis(); - while (hwMillis() - enter < 2) {} - if (hwDigitalRead(MY_NODE_UNLOCK_PIN) == 0) { - // Pin is grounded, reset lock counter - hwWriteConfig(EEPROM_NODE_LOCK_COUNTER_ADDRESS, MY_NODE_LOCK_COUNTER_MAX); - // Disable pullup - hwPinMode(MY_NODE_UNLOCK_PIN, INPUT); - setIndication(INDICATION_ERR_LOCKED); - CORE_DEBUG(PSTR("MCO:BGN:NODE UNLOCKED\n")); - } else { - // Disable pullup - hwPinMode(MY_NODE_UNLOCK_PIN, INPUT); - _nodeLock("LDB"); //Locked during boot - } - } else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER_ADDRESS) == 0xFF) { - // Reset value - hwWriteConfig(EEPROM_NODE_LOCK_COUNTER_ADDRESS, MY_NODE_LOCK_COUNTER_MAX); - } -#endif -} -#if DOXYGEN - -#endif diff --git a/lib/MySensors/core/MySensorsCore.h b/lib/MySensors/core/MySensorsCore.h deleted file mode 100644 index cb685a15..00000000 --- a/lib/MySensors/core/MySensorsCore.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** -* @file MySensorsCore.h -* -* @defgroup MySensorsCoregrp MySensorsCore -* @ingroup internals -* @{ -* -* MySensorsCore-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE -* - [!] Exclamation mark is prepended in case of error or warning -* - SYSTEM: -* - MCO messages emitted by MySensorsCore -* - SUB SYSTEMS: -* - MCO:BGN from @ref _begin() -* - MCO:REG from @ref _registerNode() -* - MCO:SND from @ref send() -* - MCO:PIM from @ref _processInternalCoreMessage() -* - MCO:NLK from @ref _nodeLock() -* -* MySensorsCore debug log messages: -* -* |E| SYS | SUB | Message | Comment -* |-|-----|-----|---------------------------------------------|----------------------------------------------------------------------------------------------------------------- -* |!| MCO | BGN | HW ERR | Error HW initialization (e.g. ext. EEPROM) -* | | MCO | BGN | INIT %%s,CP=%%s,FQ=%%d,REL=%%d,VER=%%s | Core initialization, capabilities (CP), CPU frequency [Mhz] (FQ), release number (REL), library version (VER) -* | | MCO | BGN | BFR | Callback before() -* | | MCO | BGN | STP | Callback setup() -* | | MCO | BGN | INIT OK,TSP=%%d | Core initialised, transport status (TSP): 0=not initialised, 1=initialised, NA=not available -* | | MCO | BGN | NODE UNLOCKED | Node successfully unlocked (see signing chapter) -* |!| MCO | BGN | TSP FAIL | Transport initialization failed -* | | MCO | REG | REQ | Registration request -* | | MCO | REG | NOT NEEDED | No registration needed (i.e. GW) -* |!| MCO | SND | NODE NOT REG | Node is not registered, cannot send message -* | | MCO | PIM | NODE REG=%%d | Registration response received, registration status (REG) -* |!| MCO | WAI | RC=%%d | Recursive call detected in wait(), level (RC) -* | | MCO | SLP | MS=%%lu,SMS=%%d,I1=%%d,M1=%%d,I2=%%d,M2=%%d | Sleep node, time (MS), smartSleep (SMS), Int1 (I1), Mode1 (M1), Int2 (I2), Mode2 (M2) -* | | MCO | SLP | WUP=%%d | Node woke-up, reason/IRQ (WUP) -* |!| MCO | SLP | NTL | Sleeping not possible, no time left -* |!| MCO | SLP | FWUPD | Sleeping not possible, FW update ongoing -* |!| MCO | SLP | REP | Sleeping not possible, repeater feature enabled -* |!| MCO | SLP | TNR | Transport not ready, attempt to reconnect until timeout (@ref MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS) -* | | MCO | NLK | NODE LOCKED. UNLOCK: GND PIN %%d AND RESET | Node locked during booting, see signing chapter for additional information -* | | MCO | NLK | TSL | Set transport to sleep -* -* @brief API declaration for MySensorsCore -*/ - - -#ifndef MySensorsCore_h -#define MySensorsCore_h - -#include "Version.h" -#include "MyConfig.h" -#include "MyEepromAddresses.h" -#include "MyMessage.h" -#include -#include - -#define GATEWAY_ADDRESS ((uint8_t)0) //!< Node ID for GW sketch -#define NODE_SENSOR_ID ((uint8_t)255) //!< Node child is always created/presented when a node is started -#define MY_CORE_VERSION ((uint8_t)2) //!< core version -#define MY_CORE_MIN_VERSION ((uint8_t)2) //!< min core version required for compatibility - -#define MY_WAKE_UP_BY_TIMER ((int8_t)-1) //!< Sleeping wake up by timer -#define MY_SLEEP_NOT_POSSIBLE ((int8_t)-2) //!< Sleeping not possible -#define INTERRUPT_NOT_DEFINED ((uint8_t)255) //!< _sleep() param: no interrupt defined -#define MODE_NOT_DEFINED ((uint8_t)255) //!< _sleep() param: no mode defined -#define VALUE_NOT_DEFINED ((uint8_t)255) //!< Value not defined -#define FUNCTION_NOT_SUPPORTED ((uint16_t)0) //!< Function not supported - -/** - * @brief Controller configuration - * - * This structure stores controller-related configurations - */ -typedef struct { - uint8_t isMetric; //!< Flag indicating if metric or imperial measurements are used -} controllerConfig_t; - -/** -* @brief Node core configuration -*/ -typedef struct { - controllerConfig_t controllerConfig; //!< Controller config - // 8 bit - bool nodeRegistered : 1; //!< Flag node registered - bool presentationSent : 1; //!< Flag presentation sent - uint8_t reserved : 6; //!< reserved -} coreConfig_t; - - -// **** public functions ******** - -/** - * Return this nodes id. - */ -uint8_t getNodeId(void); - -/** - * Return the parent node id. - */ -uint8_t getParentNodeId(void); - -/** -* Sends node information to the gateway. -*/ -void presentNode(void); - -/** - * Each node must present all attached sensors before any values can be handled correctly by the controller. - * It is usually good to present all attached sensors after power-up in setup(). - * - * @param sensorId Select a unique sensor id for this sensor. Choose a number between 0-254. - * @param sensorType The sensor type. See sensor typedef in MyMessage.h. - * @param description A textual description of the sensor. - * @param requestEcho Set this to true if you want destination node to echo the message back to this node. - * Default is not to request echo. If set to true, the final destination will echo back the - * contents of the message, triggering the receive() function on the original node with a copy of - * the message, with message.isEcho() set to true and sender/destination switched. - * @return true Returns true if message reached the first stop on its way to destination. - */ -bool present(const uint8_t sensorId, const mysensors_sensor_t sensorType, - const char *description = "", - const bool requestEcho = false); -#if !defined(__linux__) -bool present(const uint8_t childSensorId, const mysensors_sensor_t sensorType, - const __FlashStringHelper *description, - const bool requestEcho = false); -#endif -/** - * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. - * @param name String containing a short Sketch name or NULL if not applicable - * @param version String containing a short Sketch version or NULL if not applicable - * @param requestEcho Set this to true if you want destination node to echo the message back to this node. - * Default is not to request echo. If set to true, the final destination will echo back the - * contents of the message, triggering the receive() function on the original node with a copy of - * the message, with message.isEcho() set to true and sender/destination switched. - * @return true Returns true if message reached the first stop on its way to destination. - */ -bool sendSketchInfo(const char *name, const char *version, const bool requestEcho = false); -#if !defined(__linux__) -bool sendSketchInfo(const __FlashStringHelper *name, const __FlashStringHelper *version, - const bool requestEcho = false); -#endif - -/** - * Sends a message to gateway or one of the other nodes in the radio network - * @param msg Message to send - * @param requestEcho Set this to true if you want destination node to echo the message back to this node. - * Default is not to request echo. If set to true, the final destination will echo back the - * contents of the message, triggering the receive() function on the original node with a copy of - * the message, with message.isEcho() set to true and sender/destination switched. - * @return true Returns true if message reached the first stop on its way to destination. - */ -bool send(MyMessage &msg, const bool requestEcho = false); - -/** - * Send this nodes battery level to gateway. - * @param level Level between 0-100(%) - * @param requestEcho Set this to true if you want destination node to echo the message back to this node. - * Default is not to request echo. If set to true, the final destination will echo back the - * contents of the message, triggering the receive() function on the original node with a copy of - * the message, with message.isEcho() set to true and sender/destination switched. - * @return true Returns true if message reached the first stop on its way to destination. - */ -bool sendBatteryLevel(const uint8_t level, const bool requestEcho = false); - -/** - * Send a heartbeat message (I'm alive!) to the gateway/controller. - * The payload will be an incremental 16 bit integer value starting at 1 when sensor is powered on. - * @param requestEcho Set this to true if you want destination node to echo the message back to this node. - * Default is not to request echo. If set to true, the final destination will echo back the - * contents of the message, triggering the receive() function on the original node with a copy of - * the message, with message.isEcho() set to true and sender/destination switched. - * @return true Returns true if message reached the first stop on its way to destination. - */ -bool sendHeartbeat(const bool requestEcho = false); - -/** - * Send this nodes signal strength to gateway. - * @param level Signal strength can be RSSI if the radio provide it, or another kind of calculation - * @param requestEcho Set this to true if you want destination node to echo the message back to this node. - * Default is not to request echo. If set to true, the final destination will echo back the - * contents of the message, triggering the receive() function on the original node with a copy of - * the message, with message.isEcho() set to true and sender/destination switched. - * @return true Returns true if message reached the first stop on its way to destination. - */ -bool sendSignalStrength(const int16_t level, const bool requestEcho = false); - -/** - * Send this nodes TX power level to gateway. - * @param level For instance, can be TX power level in dbm - * @param requestEcho Set this to true if you want destination node to echo the message back to this node. - * Default is not to request echo. If set to true, the final destination will echo back the - * contents of the message, triggering the receive() function on the original node with a copy of - * the message, with message.isEcho() set to true and sender/destination switched. - * @return true Returns true if message reached the first stop on its way to destination. - */ -bool sendTXPowerLevel(const uint8_t level, const bool requestEcho = false); - -/** -* Requests a value from gateway or some other sensor in the radio network. -* Make sure to add callback-method in begin-method to handle request responses. -* -* @param childSensorId The unique child id for the different sensors connected to this Arduino. 0-254. -* @param variableType The variableType to fetch -* @param destination The nodeId of other node in radio network. Default is gateway -* @return true Returns true if message reached the first stop on its way to destination. -*/ -bool request(const uint8_t childSensorId, const uint8_t variableType, - const uint8_t destination = GATEWAY_ADDRESS); - -/** - * Requests time from controller. Answer will be delivered to receiveTime function in sketch. - * @param requestEcho Set this to true if you want destination node to echo the message back to this node. - * Default is not to request echo. If set to true, the final destination will echo back the - * contents of the message, triggering the receive() function on the original node with a copy of - * the message, with message.isEcho() set to true and sender/destination switched. - * @return true Returns true if message reached the first stop on its way to destination. - */ -bool requestTime(const bool requestEcho = false); - -/** - * Returns the most recent node configuration received from controller - */ -controllerConfig_t getControllerConfig(void); - -/** - * Save a state (in local EEPROM). Good for actuators to "remember" state between - * power cycles. - * - * You have 256 bytes to play with. Note that there is a limitation on the number - * of writes the EEPROM can handle (~100 000 cycles on ATMega328). - * - * @param pos The position to store value in (0-255) - * @param value to store in position - */ -void saveState(const uint8_t pos, const uint8_t value); - -/** - * Load a state (from local EEPROM). - * - * @param pos The position to fetch value from (0-255) - * @return Value to store in position - */ -uint8_t loadState(const uint8_t pos); - -/** - * Wait for a specified amount of time to pass. Keeps process()ing. - * This does not power-down the radio nor the Arduino. - * Because this calls process() in a loop, it is a good way to wait - * in your loop() on a repeater node or sensor that listens to messages. - * @param waitingMS Number of milliseconds to wait. - */ -void wait(const uint32_t waitingMS); - -/** - * Wait for a specified amount of time to pass or until specified message received. Keeps process()ing. - * This does not power-down the radio nor the Arduino. - * Because this calls process() in a loop, it is a good way to wait - * in your loop() on a repeater node or sensor that listens to messages. - * @param waitingMS Number of milliseconds to wait. - * @param cmd Command of incoming message. - * @return True if specified message received - */ -bool wait(const uint32_t waitingMS, const mysensors_command_t cmd); - -/** - * Wait for a specified amount of time to pass or until specified message received. Keeps process()ing. - * This does not power-down the radio nor the Arduino. - * Because this calls process() in a loop, it is a good way to wait - * in your loop() on a repeater node or sensor that listens to messages. - * @param waitingMS Number of milliseconds to wait. - * @param cmd Command of incoming message. - * @param msgtype Message type. - * @return True if specified message received - */ -bool wait(const uint32_t waitingMS, const mysensors_command_t cmd, const uint8_t msgtype); - -/** - * Function to allow scheduler to do some work. - * @remark Internally it will call yield, kick the watchdog and update led states. - */ -void doYield(void); - - -/** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer. - * @param sleepingMS Number of milliseconds to sleep. - * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep. - * @return @ref MY_WAKE_UP_BY_TIMER if timer woke it up, @ref MY_SLEEP_NOT_POSSIBLE if not possible (e.g. ongoing FW update) - */ -int8_t sleep(const uint32_t sleepingMS, const bool smartSleep = false); - -/** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change. - * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin - * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 - * @param interrupt Interrupt that should trigger the wakeup - * @param mode RISING, FALLING, CHANGE - * @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever - * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep - * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) - */ -int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0, - const bool smartSleep = false); - -/** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. - * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin - * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 - * @param interrupt1 First interrupt that should trigger the wakeup - * @param mode1 Mode for first interrupt (RISING, FALLING, CHANGE) - * @param interrupt2 Second interrupt that should trigger the wakeup - * @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) - * @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever - * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep. - * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) - */ -int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false); - -/** -* \deprecated Use sleep(ms, true) instead -* Same as sleep(), send heartbeat and process incoming messages before going to sleep. -* Specify the time to wait for incoming messages by defining @ref MY_SMART_SLEEP_WAIT_DURATION_MS to a time (ms). -* @param sleepingMS Number of milliseconds to sleep. -* @return @ref MY_WAKE_UP_BY_TIMER if timer woke it up, @ref MY_SLEEP_NOT_POSSIBLE if not possible (e.g. ongoing FW update) -*/ -int8_t smartSleep(const uint32_t sleepingMS); - -/** -* \deprecated Use sleep(interrupt, mode, ms, true) instead -* Same as sleep(), send heartbeat and process incoming messages before going to sleep. -* Specify the time to wait for incoming messages by defining @ref MY_SMART_SLEEP_WAIT_DURATION_MS to a time (ms). -* @param interrupt Interrupt that should trigger the wakeup -* @param mode RISING, FALLING, CHANGE -* @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever -* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) -*/ -int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0); - -/** -* \deprecated Use sleep(interrupt1, mode1, interrupt2, mode2, ms, true) instead -* Same as sleep(), send heartbeat and process incoming messages before going to sleep. -* Specify the time to wait for incoming messages by defining @ref MY_SMART_SLEEP_WAIT_DURATION_MS to a time (ms). -* @param interrupt1 First interrupt that should trigger the wakeup -* @param mode1 Mode for first interrupt (RISING, FALLING, CHANGE) -* @param interrupt2 Second interrupt that should trigger the wakeup -* @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) -* @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever -* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) -*/ -int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, const uint32_t sleepingMS = 0); - -/** -* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. -* See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin -* is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 -* @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever -* @param interrupt1 (optional) First interrupt that should trigger the wakeup -* @param mode1 (optional) Mode for first interrupt (RISING, FALLING, CHANGE) -* @param interrupt2 (optional) Second interrupt that should trigger the wakeup -* @param mode2 (optional) Mode for second interrupt (RISING, FALLING, CHANGE) -* @param smartSleep (optional) Set True if sending heartbeat and process incoming messages before going to sleep. -* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) -*/ -int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false, - const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, - const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED); - -/** - * Return the sleep time remaining after waking up from sleep. - * Depending on the CPU architecture, the remaining time can be seconds off (e.g. upto roughly 8 seconds on AVR). - * @return Time remaining, in ms, when wake from sleep by an interrupt, 0 by timer (@ref MY_WAKE_UP_BY_TIMER), undefined otherwise. -*/ -uint32_t getSleepRemaining(void); - - -// **** private functions ******** - -/** - * @defgroup MyLockgrp MyNodeLock - * @ingroup internals - * @brief API declaration for MyNodeLock - * @{ - */ -/** - * @brief Lock a node and transmit provided message with 30m intervals - * - * This function is called if suspicious activity has exceeded the threshold (see - * @ref MY_NODE_LOCK_COUNTER_MAX). Unlocking with a normal Arduino bootloader require erasing the EEPROM - * while unlocking with a custom bootloader require holding @ref MY_NODE_UNLOCK_PIN low during power on/reset. - * - * @param str The string to transmit. - */ -void _nodeLock(const char *str); - -/** - * @brief Check node lock status and prevent node execution if locked. - */ -void _checkNodeLock(void); -/** @}*/ // Node lock group - -/** -* @brief Node initialisation -*/ -void _begin(void); -/** -* @brief Main framework process -*/ -void _process(void); -/** -* @brief Processes internal core message -* @return True if no further processing required -*/ -bool _processInternalCoreMessage(void); -/** -* @brief Puts node to a infinite loop if unrecoverable situation detected -*/ -void _infiniteLoop(void); -/** -* @brief Handles registration request -*/ -void _registerNode(void); -/** -* @brief Sends message according to routing table -* @param message -* @return true Returns true if message reached the first stop on its way to destination. -*/ -bool _sendRoute(MyMessage &message); -/** -* @brief Callback for incoming messages -*/ -void receive(const MyMessage&) __attribute__((weak)); -/** -* @brief Callback for incoming time messages -*/ -void receiveTime(uint32_t) __attribute__((weak)); -/** -* @brief Node presentation -*/ -void presentation(void) __attribute__((weak)); -/** -* @brief Called before node initialises -*/ -void before(void) __attribute__((weak)); -/** -* @brief Called before any hardware initialisation is done -*/ -void preHwInit(void) __attribute__((weak)); -/** -* @brief Called after node initialises but before main loop -*/ -void setup(void) __attribute__((weak)); -/** -* @brief Main loop -*/ -void loop(void) __attribute__((weak)); - - -// Inline function and macros -static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor, - const mysensors_command_t command, const uint8_t type, const bool requestEcho = false) -{ - msg.setSender(getNodeId()); - msg.setDestination(destination); - msg.setSensor(sensor); - msg.setType(type); - msg.setCommand(command); - msg.setRequestEcho(requestEcho); - msg.setEcho(false); - return msg; -} - -static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type) -{ - msg.setSender(GATEWAY_ADDRESS); - msg.setDestination(GATEWAY_ADDRESS); - msg.setSensor(NODE_SENSOR_ID); - msg.setType(type); - msg.setCommand(C_INTERNAL); - msg.setRequestEcho(false); - msg.setEcho(false); - return msg; -} - -#endif - -/** @}*/ diff --git a/lib/MySensors/core/MySigning.cpp b/lib/MySensors/core/MySigning.cpp deleted file mode 100644 index dddf91a8..00000000 --- a/lib/MySensors/core/MySigning.cpp +++ /dev/null @@ -1,587 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MySigning.h" - -#define SIGNING_PRESENTATION_VERSION_1 1 -#define SIGNING_PRESENTATION_REQUIRE_SIGNATURES (1 << 0) -#define SIGNING_PRESENTATION_REQUIRE_WHITELISTING (1 << 1) - -#if defined(MY_DEBUG_VERBOSE_SIGNING) -#define SIGN_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) -#else -#define SIGN_DEBUG(x,...) -#endif - -#if defined(MY_SIGNING_REQUEST_SIGNATURES) &&\ - (!defined(MY_SIGNING_ATSHA204) && !defined(MY_SIGNING_SOFT)) -#error You have to pick either MY_SIGNING_ATSHA204 or MY_SIGNING_SOFT to reqire signatures! -#endif -#if defined(MY_SIGNING_SOFT) && defined(MY_SIGNING_ATSHA204) -#error You have to pick one and only one signing backend -#endif -#ifdef MY_SIGNING_FEATURE -static uint8_t _doSign[32]; // Bitfield indicating which sensors require signed communication -static uint8_t _doWhitelist[32]; // Bitfield indicating which sensors require salted signatures -static MyMessage _msgSign; // Buffer for message to sign. -static uint8_t _signingNonceStatus; -static bool stateValid = false; - -#ifdef MY_NODE_LOCK_FEATURE -static uint8_t nof_nonce_requests = 0; -static uint8_t nof_failed_verifications = 0; -#endif - -// Status when waiting for signing nonce in signerSignMsg -enum { SIGN_WAITING_FOR_NONCE = 0, SIGN_OK = 1 }; - -// Macros for manipulating signing requirement tables -#define DO_SIGN(node) (~_doSign[node>>3]&(1<>3]&=~(1<>3]|=(1<>3]&(1<>3]&=~(1<>3]|=(1< MY_VERIFICATION_TIMEOUT_MS) { - SIGN_DEBUG(PSTR("!SGN:SGN:NCE TMO\n")); // Timeout waiting for nonce! - ret = false; - } else { - if (_signingNonceStatus == SIGN_OK) { - // process() received a nonce and signerProcessInternal successfully signed the message - msg = _msgSign; // Write the signed message back - SIGN_DEBUG(PSTR("SGN:SGN:SGN\n")); // Message to send has been signed - ret = true; - // After this point, only the 'last' member of the message structure is allowed to be - // altered if the message has been signed, or signature will become invalid and the - // message rejected by the receiver - } else { - SIGN_DEBUG(PSTR("!SGN:SGN:SGN FAIL\n")); // Message to send could not be signed! - ret = false; - } - } - } - } - } - } else if (getNodeId() == msg.getSender()) { - msg.setSigned(false); // Message is not supposed to be signed, make sure it is marked unsigned - SIGN_DEBUG(PSTR("SGN:SGN:NREQ=%" PRIu8 "\n"), - msg.getDestination()); // Do not sign message as it is not req - ret = true; - } else { - SIGN_DEBUG(PSTR("SGN:SGN:%" PRIu8 "!=%" PRIu8 " NUS\n"), msg.getSender(), - getNodeId()); // Will not sign message since it was from someone else - ret = true; - } - return ret; -#else - (void)msg; - return true; -#endif // MY_SIGNING_FEATURE - -} - -bool signerVerifyMsg(MyMessage &msg) -{ - bool verificationResult = true; - // Before processing message, reject unsigned messages if signing is required and check signature - // (if it is signed and addressed to us) - // Note that we do not care at all about any signature found if we do not require signing -#if defined(MY_SIGNING_FEATURE) && defined(MY_SIGNING_REQUEST_SIGNATURES) - // If we are a node, or we are a gateway and the sender require signatures (or just a strict gw) - // and we are the destination... -#if defined(MY_SIGNING_WEAK_SECURITY) - if ((!MY_IS_GATEWAY || DO_SIGN(msg.getSender())) && msg.getDestination() == getNodeId()) { -#else - if (msg.getDestination() == getNodeId()) { -#endif - // Internal messages of certain types are not verified - if (skipSign(msg)) { - verificationResult = true; - } else if (!msg.getSigned()) { - // Got unsigned message that should have been signed - SIGN_DEBUG(PSTR("!SGN:VER:NSG\n")); // Message is not signed, but it should have been! - verificationResult = false; - } else { - // Before starting, validate that our state is good, or signing will fail - if (!stateValid) { - SIGN_DEBUG(PSTR("!SGN:VER:STATE\n")); // Signing system is not in a valid state - verificationResult = false; - } else { - if (!signerBackendVerifyMsg(msg)) { - SIGN_DEBUG(PSTR("!SGN:VER:FAIL\n")); // Signature verification failed! - verificationResult = false; - } else { - SIGN_DEBUG(PSTR("SGN:VER:OK\n")); - } - } -#if defined(MY_NODE_LOCK_FEATURE) - if (verificationResult) { - // On successful verification, clear lock counters - nof_nonce_requests = 0; - nof_failed_verifications = 0; - } else { - nof_failed_verifications++; - SIGN_DEBUG(PSTR("SGN:VER:LEFT=%" PRIu8 "\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications); - if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) { - _nodeLock("TMFV"); // Too many failed verifications - } - } -#endif - msg.setSigned(false); // Clear the sign-flag now as verification is completed - } - } -#else - (void)msg; -#endif // MY_SIGNING_REQUEST_SIGNATURES - return verificationResult; -} - -int signerMemcmp(const void* a, const void* b, size_t sz) -{ - int retVal; - size_t i; - int done = 0; - const uint8_t* ptrA = (const uint8_t*)a; - const uint8_t* ptrB = (const uint8_t*)b; - for (i=0; i < sz; i++) { - if (ptrA[i] == ptrB[i]) { - if (done > 0) { - done = 1; - } else { - done = 0; - } - } else { - if (done > 0) { - done = 2; - } else { - done = 3; - } - } - } - if (done > 0) { - retVal = -1; - } else { - retVal = 0; - } - return retVal; -} - -#if defined(MY_SIGNING_FEATURE) -// Helper function to centralize signing/verification exceptions -static bool skipSign(MyMessage &msg) -{ - bool ret = false; - if (msg.isEcho()) { - ret = true; - } else if (msg.getCommand() == C_INTERNAL && - (msg.getType() == I_SIGNING_PRESENTATION || - msg.getType() == I_REGISTRATION_REQUEST || - msg.getType() == I_NONCE_REQUEST || msg.getType() == I_NONCE_RESPONSE || - msg.getType() == I_ID_REQUEST || msg.getType() == I_ID_RESPONSE || - msg.getType() == I_FIND_PARENT_REQUEST || msg.getType() == I_FIND_PARENT_RESPONSE || - msg.getType() == I_HEARTBEAT_REQUEST || msg.getType() == I_HEARTBEAT_RESPONSE || - msg.getType() == I_PING || msg.getType() == I_PONG || - msg.getType() == I_DISCOVER_REQUEST || msg.getType() == I_DISCOVER_RESPONSE || - msg.getType() == I_LOG_MESSAGE)) { - ret = true; - } else if (msg.getCommand() == C_STREAM && - (msg.getType() == ST_SOUND || - msg.getType() == ST_IMAGE || - msg.getType() == ST_FIRMWARE_REQUEST || msg.getType() == ST_FIRMWARE_RESPONSE )) { - ret = true; - } - if (ret) { - SIGN_DEBUG(PSTR("SGN:SKP:%s CMD=%" PRIu8 ",TYPE=%" PRIu8 "\n"), msg.isEcho() ? "ECHO" : "MSG", - msg.getCommand(), - msg.getType()); //Skip signing/verification of this message - } - return ret; -} -#endif - -// Helper to prepare a signing presentation message -static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) -{ - // Only supports version 1 for now - (void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set(""); - msg.setLength(2); - msg.setPayloadType(P_CUSTOM); // displayed as hex - msg.data[0] = SIGNING_PRESENTATION_VERSION_1; - msg.data[1] = 0; -} - -// Helper to process presentation messages -static bool signerInternalProcessPresentation(MyMessage &msg) -{ - const uint8_t sender = msg.getSender(); -#if defined(MY_SIGNING_FEATURE) - if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) { - SIGN_DEBUG(PSTR("!SGN:PRE:VER=%" PRIu8 "\n"), - msg.data[0]); // Unsupported signing presentation version - return true; // Just drop this presentation message - } - // We only handle version 1 here... - if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) { - // We received an indicator that the sender require us to sign all messages we send to it - SIGN_DEBUG(PSTR("SGN:PRE:SGN REQ,FROM=%" PRIu8 "\n"), sender); // Node require signatures - SET_SIGN(sender); - } else { -#if defined(MY_SIGNING_WEAK_SECURITY) - // We received an indicator that the sender does not require us to sign messages we send to it - SIGN_DEBUG(PSTR("SGN:PRE:SGN NREQ,FROM=%" PRIu8 "\n"), sender); // Node does not require signatures - CLEAR_SIGN(sender); -#else - if (DO_SIGN(sender)) { - SIGN_DEBUG(PSTR("!SGN:PRE:SGN NREQ,FROM=%" PRIu8 " REJ\n"), - sender); // Node does not require signatures but used to do so - } -#endif - } - if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) { - // We received an indicator that the sender require us to salt signatures with serial - SIGN_DEBUG(PSTR("SGN:PRE:WHI REQ,FROM=%" PRIu8 "\n"), sender); // Node require whitelisting - SET_WHITELIST(sender); - } else { -#if defined(MY_SIGNING_WEAK_SECURITY) - // We received an indicator that the sender does not require us to sign messages we send to it - SIGN_DEBUG(PSTR("SGN:PRE:WHI NREQ,FROM=%" PRIu8 "\n"), - sender); // Node does not require whitelisting - CLEAR_WHITELIST(sender); -#else - if (DO_WHITELIST(sender)) { - SIGN_DEBUG(PSTR("!SGN:PRE:WHI NREQ,FROM=%" PRIu8 " REJ\n"), - sender); // Node does not require whitelisting but used to do so - } -#endif - } - - // Save updated tables - hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, - sizeof(_doSign)); - hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS, - sizeof(_doWhitelist)); - - // Inform sender about our preference if we are a gateway, but only require signing if the sender - // required signing unless we explicitly configure it to -#if defined(MY_GATEWAY_FEATURE) - prepareSigningPresentation(msg, sender); -#if defined(MY_SIGNING_REQUEST_SIGNATURES) -#if defined(MY_SIGNING_WEAK_SECURITY) - if (DO_SIGN(sender)) { - msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES; - } -#else - msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES; -#endif -#endif // MY_SIGNING_REQUEST_SIGNATURES -#if defined(MY_SIGNING_NODE_WHITELISTING) - msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING; -#endif // MY_SIGNING_NODE_WHITELISTING - if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) { - SIGN_DEBUG(PSTR("SGN:PRE:SGN REQ,TO=%" PRIu8 "\n"), - sender); // Inform node that we require signatures - } else { - SIGN_DEBUG(PSTR("SGN:PRE:SGN NREQ,TO=%" PRIu8 "\n"), - sender); // Inform node that we do not require signatures - } - if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) { - SIGN_DEBUG(PSTR("SGN:PRE:WHI REQ,TO=%" PRIu8 "\n"), - sender); // Inform node that we require whitelisting - } else { - SIGN_DEBUG(PSTR("SGN:PRE:WHI NREQ,TO=%" PRIu8 "\n"), - sender); // Inform node that we do not require whitelisting - } - if (!_sendRoute(msg)) { - SIGN_DEBUG(PSTR("!SGN:PRE:XMT,TO=%" PRIu8 " FAIL\n"), - sender); // Failed to transmit signing presentation! - } else { - SIGN_DEBUG(PSTR("SGN:PRE:XMT,TO=%" PRIu8 "\n"), sender); - } -#endif // MY_GATEWAY_FEATURE -#else // not MY_SIGNING_FEATURE -#if defined(MY_GATEWAY_FEATURE) - // If we act as gateway and do not have the signing feature and receive a signing request we still - // need to do make sure the requester does not believe the gateway still require signatures - prepareSigningPresentation(msg, sender); - SIGN_DEBUG(PSTR("SGN:PRE:NSUP,TO=%" PRIu8 "\n"), - sender); // Informing node that we do not support signing - if (!_sendRoute(msg)) { - SIGN_DEBUG(PSTR("!SGN:PRE:XMT,TO=%" PRIu8 " FAIL\n"), - sender); // Failed to transmit signing presentation! - } else { - SIGN_DEBUG(PSTR("SGN:PRE:XMT,TO=%" PRIu8 "\n"), sender); - } -#else // not MY_GATEWAY_FEATURE - // If we act as a node and do not have the signing feature then we just silently drop any signing - // presentation messages received - (void)msg; - (void)sender; - // Received signing presentation, but signing is not supported (message ignored) - SIGN_DEBUG( - PSTR("SGN:PRE:NSUP\n")); -#endif // not MY_GATEWAY_FEATURE -#endif // not MY_SIGNING_FEATURE - return true; // No need to further process I_SIGNING_PRESENTATION -} - -// Helper to process nonce request messages -static bool signerInternalProcessNonceRequest(MyMessage &msg) -{ -#if defined(MY_SIGNING_FEATURE) -#if defined(MY_NODE_LOCK_FEATURE) - nof_nonce_requests++; - SIGN_DEBUG(PSTR("SGN:NCE:LEFT=%" PRIu8 "\n"), - MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests); // Nonce requests left until lockdown - if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) { - _nodeLock("TMNR"); // Too many nonces requested - } -#endif // MY_NODE_LOCK_FEATURE - if (signerBackendGetNonce(msg)) { - if (!_sendRoute(build(msg, msg.getSender(), NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) { - SIGN_DEBUG(PSTR("!SGN:NCE:XMT,TO=%" PRIu8 " FAIL\n"), msg.getSender()); // Failed to transmit nonce! - } else { - SIGN_DEBUG(PSTR("SGN:NCE:XMT,TO=%" PRIu8 "\n"), msg.getSender()); - } - } else { - SIGN_DEBUG(PSTR("!SGN:NCE:GEN\n")); // Failed to generate nonce! - } -#else // not MY_SIGNING_FEATURE - (void)msg; - SIGN_DEBUG( - PSTR("SGN:NCE:NSUP (DROPPED)\n")); // Received nonce request/response without signing support -#endif // MY_SIGNING_FEATURE - return true; // No need to further process I_NONCE_REQUEST -} - -// Helper to process nonce response messages -static bool signerInternalProcessNonceResponse(MyMessage &msg) -{ -#if defined(MY_SIGNING_FEATURE) - // Proceed with signing if nonce has been received - SIGN_DEBUG(PSTR("SGN:NCE:FROM=%" PRIu8 "\n"), msg.getSender()); - if (msg.getSender() != _msgSign.getDestination()) { - SIGN_DEBUG(PSTR("SGN:NCE:%" PRIu8 "!=%" PRIu8 " (DROPPED)\n"), _msgSign.getDestination(), - msg.getSender()); - } else { - signerBackendPutNonce(msg); - if (signerBackendSignMsg(_msgSign)) { - // _msgSign now contains the signed message pending transmission - _signingNonceStatus = SIGN_OK; - } - } -#else - (void)msg; - SIGN_DEBUG( - PSTR("SGN:NCE:NSUP (DROPPED)\n")); // Received nonce request/response without signing support -#endif - return true; // No need to further process I_NONCE_RESPONSE -} - -#if (defined(MY_ENCRYPTION_FEATURE) || defined(MY_SIGNING_FEATURE)) &&\ - !defined(MY_SIGNING_SIMPLE_PASSWD) -static bool signerInternalValidatePersonalization(void) -{ -#ifdef __linux__ - // Personalization on linux is a bit more crude - return true; -#else - uint8_t buffer[SIZE_SIGNING_SOFT_HMAC_KEY + SIZE_RF_ENCRYPTION_AES_KEY + SIZE_SIGNING_SOFT_SERIAL]; - uint8_t hash[32]; - uint8_t checksum; - hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, - SIZE_SIGNING_SOFT_HMAC_KEY); - hwReadConfigBlock((void*)&buffer[SIZE_SIGNING_SOFT_HMAC_KEY], - (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, SIZE_RF_ENCRYPTION_AES_KEY); - hwReadConfigBlock((void*)&buffer[SIZE_SIGNING_SOFT_HMAC_KEY + SIZE_RF_ENCRYPTION_AES_KEY], - (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, SIZE_SIGNING_SOFT_SERIAL); - hwReadConfigBlock((void*)&checksum, (void*)EEPROM_PERSONALIZATION_CHECKSUM_ADDRESS, - SIZE_PERSONALIZATION_CHECKSUM); - - SHA256(hash, buffer, sizeof(buffer)); - return (checksum == hash[0]); -#endif -} -#endif diff --git a/lib/MySensors/core/MySigning.h b/lib/MySensors/core/MySigning.h deleted file mode 100644 index 614d78bb..00000000 --- a/lib/MySensors/core/MySigning.h +++ /dev/null @@ -1,907 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ -/** - * @defgroup MySigninggrpPub Message signing - * @ingroup publics - * @{ - * - * @brief The message signing infrastructure provides message authenticity to users by signing - * MySensors messages. - * - * Signing support created by Patrick "Anticimex" Fallberg. - * - * @section MySigninggrptoc Table of contents - * - * @ref MySigninggrphowuse
- * @ref MySigningwhitelisting
- * @ref MySigninglimitations
- * @ref MySigningusecases
- * @ref MySigningtechnical
- * @ref MySigninggrpbackground
- * @ref MySigninggrphow
- * @ref MySigninggrpencryption
- * - * @section MySigninggrphowuse How to use this - * - * Before we begin with the details, I just want to emphasize that signing is completely optional - * and not enabled by default. - * - * If you do want the additional security layer signing provides, you pick the backend of your - * choice in your sketch. Currently, two compatible backends are supported; @ref MY_SIGNING_ATSHA204 - * (hardware backed) and @ref MY_SIGNING_SOFT (software backed). There also exist a simplified - * variant (@ref MY_SIGNING_SIMPLE_PASSWD) of the software backend which only require one setting - * to activate. - * - * If you use hardware backed signing, then connect the device as follows: - * @image html MySigning/wiring.png - * @note The pull-up resistor is optional but recommended. - * @note If you change the default pin (A3) make sure you use a pin that supports input/output - * (ex. A6 & A7 on a Pro Mini are input only pins). - * - * To use signing, you need to perform three major steps which are described below. - * - * Firstly, you need to make sure to pick a backend to use. - * @code{.cpp} - * //#define MY_SIGNING_SOFT - * //#define MY_SIGNING_SIMPLE_PASSWD - * #define MY_SIGNING_ATSHA204 - * #include - * ... - * @endcode - * Make sure to set the define before the inclusion of MySensors.h. - * It is ok to mix @ref MY_SIGNING_SOFT and @ref MY_SIGNING_ATSHA204 in a network. - * They are fully compatible. It is however not recommended to use @ref MY_SIGNING_SOFT on nodes - * that are publicly accessible (more on that later). - * - * If you use @ref MY_SIGNING_SOFT or @ref MY_SIGNING_ATSHA204 you also need to decide if the node - * (or gateway) in question require messages to be signed in addition to the ability to generate - * signatures for other nodes. - * This has to be set by at least one of the nodes in a "pair" or nobody will actually start - * calculating a signature for a message. - * Just set the flag @ref MY_SIGNING_REQUEST_SIGNATURES and the node will inform the gateway that it - * expects the gateway to sign all messages sent to the node. Note that when set in a gateway, the - * gateway will require ALL nodes in the network to sign messages. - * If this behaviour is undesired, enable the flag @ref MY_SIGNING_WEAK_SECURITY which will allow - * the gateway to only require signatures from nodes that in turn require signatures. It will also - * allow the gateway (and all nodes) to "downgrade" security by clearing the signing/whitelisting - * requirements (whitelisting is described later on in the @ref MySigningwhitelisting section) in - * the EEPROM if a node presents itself as not having any security requirements. - * If @ref MY_SIGNING_WEAK_SECURITY is not set, any node that has presented itself with - * signing/whitelisting requirements will be permanently marked as such by the receiver - * (typically the gateway). The only way then to reset/revert this requirement is to clear the - * EEPROM at the receiver (or disable @ref MY_SIGNING_REQUEST_SIGNATURES, but the preference will be - * remembered if the request flag is re-enabled before EEPROM is cleared).
- * If you want to have two nodes communicate securely directly with each other, the nodes that - * require signatures must send a presentation message to all nodes it expect signed messages from - * (only the gateway is informed automatically). See @ref signerPresentation().
- * A node can have three "states" with respect to signing: - * 1. Node does not support signing in any way (neither @ref MY_SIGNING_ATSHA204, - * @ref MY_SIGNING_SOFT nor @ref MY_SIGNING_SIMPLE_PASSWD is set) - * 2. Node does support signing but don't require messages sent to it to be signed (neither - * @ref MY_SIGNING_REQUEST_SIGNATURES nor @ref MY_SIGNING_SIMPLE_PASSWD is set) - * 3. Node does support signing and require messages sent to it to be signed (@ref - * MY_SIGNING_SOFT or @ref MY_SIGNING_ATSHA204 together with @ref MY_SIGNING_REQUEST_SIGNATURES or - * @ref MY_SIGNING_SIMPLE_PASSWD are set) - * - * Secondly, you need to verify the configuration for the backend.
- * For hardware backed signing it is the pin the device is connected to. In MyConfig.h there are - * defaults which you might need to adjust to match your personal build. The setting is defined - * using @ref MY_SIGNING_ATSHA204_PIN.
- * If you use an official MySensors board (like the SenseBender GW) you do not need to set the pin, - * this is configured automatically by the Arduino board definition files. - * - * Similar to picking your backend, this can also be set in your sketch: - * @code{.cpp} - * #define MY_SIGNING_ATSHA204 - * #define MY_SIGNING_ATSHA204_PIN 4 - * #define MY_SIGNING_REQUEST_SIGNATURES - * #include - * ... - * @endcode - * For the software backed signing backend, an unconnected analog pin is required on boards that - * does not provide a hardware based random generator unit to set a random seed for the - * pseudo-random generator. - * It is important that the pin is floating, or the output of the pseudo-random generator will be - * predictable, and thus compromise the signatures. The setting is defined using - * @ref MY_SIGNING_SOFT_RANDOMSEED_PIN. The same configuration possibilities exist as with the other - * configuration options. - * - * @code{.cpp} - * #define MY_SIGNING_SOFT - * #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 - * #define MY_SIGNING_REQUEST_SIGNATURES - * #include - * ... - * @endcode - * - * An example of a node that require signatures is available in @ref SecureActuator.ino. - * - * Thirdly, if you use a signing backend and you don't use @ref MY_SIGNING_SIMPLE_PASSWD, you - * need to personalize the node. - * - * @anchor personalization If you use the ATSHA204A (@ref MY_SIGNING_ATSHA204), before any signing - * operations can be done, the device needs to be personalized. - * This can be a daunting process as it involves irreversibly writing configurations to the device, - * which cannot be undone. I have however tried to simplify the process as much as possibly by - * creating a helper-sketch specifically for this purpose in @ref SecurityPersonalizer.ino - * Note that you also need to do personalization for @ref MY_SIGNING_SOFT, but then the values are - * stored in EEPROM. - * - * To personalize a ATSHA204A do the following procedure: - * 1. Enable @ref GENERATE_KEYS_ATSHA204A
- * This will lock the ATSHA204A and generate random keys for HMAC (signing) and %AES (encryption). - * Copy the keys generated and replace the corresponding definitions under - * "User defined key data", specifically @ref MY_HMAC_KEY and @ref MY_AES_KEY. - * 2. Disable @ref GENERATE_KEYS_ATSHA204A and enable @ref PERSONALIZE_ATSHA204A
- * This will store the HMAC key to the ATSHA204A and the %AES key to EEPROM. It will also write - * a checksum of the personalization data in EEPROM to be able to detect if the data is - * altered.
- * Personalization is now complete. - * - * To personalize for software signing do the following procedure: - * 1. Enable @ref GENERATE_KEYS_SOFT
- * This will generate random keys for HMAC (signing) and %AES (encryption). - * Copy the keys generated and replace the corresponding definitions under - * "User defined key data", specifically @ref MY_HMAC_KEY and @ref MY_AES_KEY. - * 2. Disable @ref GENERATE_KEYS_SOFT and enable @ref PERSONALIZE_SOFT
- * This will store the HMAC key and the %AES key to EEPROM. It will also write - * a checksum of the personalization data in EEPROM to be able to detect if the data is - * altered.
- * Personalization is now complete. - * - * If you want to use soft signing and you want to use whitelisting (the ability to revoke/ban - * compromised nodes in the network) and your target does not provide a unique device ID, you have - * to generate a unique serial and store it in EEPROM. This can be done by replacing - * @ref PERSONALIZE_SOFT in step 2 above with @ref PERSONALIZE_SOFT_RANDOM_SERIAL. See the output - * under "Hardware security peripherals" to determine if this is necessary. - * - * When you have personalized your first device after step 2 above, you can run the same sketch on - * all devices in your network that needs to be personalized in a compatible manner. Pick - * @ref PERSONALIZE_ATSHA204A or @ref PERSONALIZE_SOFT as needed by the hardware. When the - * personalization has finished, you just program the sketch you plan to use (with the appropriate - * signing flags set). - * - * If you are using a Raspberry PI-based gateway, personalizaion is done slightly differently: - * 1. Generate keys, execute @c mysgw with arguments - * * To generate HMAC key @verbatim --gen-soft-hmac-key @endverbatim - * * To generate %AES key @verbatim --gen-aes-key @endverbatim - * * To generate a soft serial number @verbatim --gen-soft-serial @endverbatim - * 2. Update the gateway config file with the generated keys/valeus - * * For HMAC key @verbatim soft_hmac_key= @endverbatim - * * For %AES key @verbatim aes_key= @endverbatim - * * For soft serial number @verbatim soft_serial_key= @endverbatim - * - * You are now set and ready to use message signing in your network. - * As of now, the following restrictions will be applied to your nodes: - * * If a node does require signing, any unsigned message sent to the node will be rejected. - * This also applies to the gateway. - * * Your radio communication quality is expected to work fine (if any NACK happen on a signing - * related message, it will fail, and enabling signing will put maximum strain on your RF link as - * maximum sized packets are transmitted in the network). See @ref MySigningTroubleshootinggrp. - * * All nodes and gateways in a network maintain a table where the signing preferences of all nodes - * are stored. This is also stored in EEPROM so if a node or gateway reboots, the other nodes does - * not have to retransmit a signing presentation to the node for the node to start expecting signed - * messages from other nodes.
- * * By default, the signing preferences are not "downgradeable". That is, any node that at any - * point in time has indicated a signing requirement will not be able to revert this requirement at - * the receiving end (except by manual erase of the EEPROM).
- * If you for some reason need to be able to downgrade the security requirements, you can set - * @ref MY_SIGNING_WEAK_SECURITY at the receiver to allow it to downgrade the security expectations - * of the node in question.
- * You then need to reset your transmitting node, to force it to transmit updated signing - * preferences. - * - * @section MySigningwhitelisting Whitelisting and node revocation - * - * Consider the situation when you have set up your secure topology. We use the remotely operated - * garage door as an example: - * * You have a node inside your garage (considered physically inaccessible) that controls your - * garage door motor.
- * This node requires signing since you do not want an unauthorized person sending it orders to - * open the door. - * * You have a keyfob node with a signing backend that uses the same PSK as your door opener node. - * - * In this setup, your keyfob can securely transmit messages to your door node since the keyfob will - * sign the messages it sends and the door node will verify that these were sent from a trusted node - * (since it used the correct PSK). If the keyfob does not sign the messages, the door node - * will not accept them. Optionally, your keyfob sends a signed message to your gateway (which - * require signatures) and the gateway in turn sends a signed message to your garage door. - * - * One day your keyfob gets stolen or you lost it or it simply broke down. - * - * You now end up with a problem; you need some way of telling your door node that the keyfob in - * question cannot be trusted any more. You could now repersonalize all your node to switch to a - * different PSK but this obviously is a hassle. How do you make sure that the "rogue" keyfob can be - * removed from the "trusted chain"? - * - * The answer to this is whitelisting. You let your door node keep a whitelist of all nodes it - * trusts. If you stop trusting a particular node, you remove it from the nodes whitelist - * (by uploading a new sketch), and it will no longer be able to communicate signed messages to the - * door node. - * - * In case you want to be able to "whitelist" trusted nodes (in order to be able to revoke them in - * case they are lost) you also need to take note of the serial number of the ATSHA device or the - * software value stored in EEPROM. This is unique for each device. The serial number is printed - * in a copy+paste friendly format by the personalizer for this purpose.
- * The whitelist is stored on the node that require signatures. When a received message is - * verified, the serial of the sender is looked up in a list stored on the receiving node, and the - * corresponding serial stored in the list for that sender is then included in the signature - * verification process. The list is stored as the value of the flag that enables whitelisting, - * @ref MY_SIGNING_NODE_WHITELISTING.
- * - * Whitelisting is achieved by 'salting' the signature with some node-unique information known to - * the receiver. In the case of @ref MY_SIGNING_ATSHA204 this is the unique serial number programmed - * into the circuit. This unique number is never transmitted over the air in clear text, so Eve will - * not be able to figure out a "trusted" serial by snooping on the traffic.
- * Instead the value is hashed together with the senders NodeId into the HMAC signature to produce - * the final signature. The receiver will then take the originating NodeId of the signed message and - * do the corresponding calculation with the serial it has stored in it's whitelist if it finds a - * matching entry in it's whitelist. - * - * Whitelisting is an optional alternative because it adds some code and configuration options which - * might not be desirable for every user. So if you want the ability to use whitelists, you need to - * enable @ref MY_SIGNING_NODE_WHITELISTING. You need to remember that the gateway will remember if - * a node has presented it with a whitelisting requirement as described above, if you at some point - * decide to remove the whitelist requirement.
- * The whitelist is provided as value of the flag that enable it as follows (example is a node that - * require signing as well): - * @code{.cpp} - * #define MY_SIGNING_ATSHA204 - * #define MY_SIGNING_REQUEST_SIGNATURES - * #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}},{.nodeId = 2,.serial = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}}} - * #include - * ... - * @endcode - * In this example, there are two nodes in the whitelist; the gateway, and a separate node that - * communicates directly with this node (with signed messages). You do not need to do anything - * special for the sending nodes, apart from making sure they support signing. - * - * The "soft" backend of course also support whitelisting. Example: - * @code{.cpp} - * #define MY_SIGNING_SOFT - * #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 - * #define MY_SIGNING_REQUEST_SIGNATURES - * #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}},{.nodeId = 2,.serial = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}}} - * #include - * ... - * @endcode - * - * For a node that should transmit whitelisted messages but not receive whitelisted messages, you do - * not need any special configurations: - * @code{.cpp} - * #define MY_SIGNING_SOFT - * #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 - * @endcode - * Remember that you always need to select a signing backend for all nodes that communicate to a - * node that require whitelisting. Also, note that a node that use whitelisting will not accept - * messages from nodes that are not present in it's whitelist. - * And you have to personalize all nodes that use signing with a common HMAC key but different - * serial numbers (@ref MY_SIGNING_ATSHA204 always has unique serials). - * - * @section MySigninglimitations Known limitations - * - * Due to the limiting factor of our cheapest Arduino nodes, the use of diversified keys is not - * implemented. That mean that all nodes in your network share the same PSK (at least the ones that - * are supposed to exchange signed data). It is important to understand the implications of - * this, and that is covered in the "Typical use cases" chapter below.
- * Most importantly, if you use @ref MY_SIGNING_SOFT your PSK will be stored in EEPROM and will - * therefore be accessible by anyone with physical access to your node. Therefore it is NOT - * recommended to use @ref MY_SIGNING_SOFT on nodes that are placed in a public place or worn on - * on your person (like a keyfob).
- * Also be reminded that the strength of the signature is inversely proportional to the size of the - * message. The larger the message, the weaker the signature. - * - * @section MySigningusecases Typical use cases - * - * "Securely located" in this context mean a node which is not physically publicly accessible. - * Typically at least your gateway.
- * "Public" in this context mean a node that is located outside your "trusted environment". This - * includes sensors located outdoors, keyfobs etc. - * - * @subsection MySigninglock Securely located lock - * - * You have a securely located gateway and a lock somewhere inside your "trusted environment" (e.g. - * inside your house door, the door to your dungeon or similar).
- * You need to make your node require signed messages but you do not necessarily need to make your - * gateway require signed messages (unless you are concerned that someone might spoof the lock - * status of your lock).
- * Configuration example for the secure lock node:
- * @code{.cpp} - * #define MY_SIGNING_ATSHA204 - * #define MY_SIGNING_REQUEST_SIGNATURES - * #include - * ... - * @endcode - * If you do also want your gateway to require signatures from your lock you just enable the same - * (or similar if using software signing) settings in the gateway. - * - * @subsection MySigningpatio Patio motion sensor - * - * Your gateway is securely located inside your house, but your motion sensor is located outside - * your house. You have for some reason elected that this node should sign the messages it send to - * your gateway. You should lock the data (PSK) in this node then, because if someone were to steal - * your patio motion sensor, they could rewrite the firmware and spoof your gateway to use it to - * transmit a correctly signed message to your secure lock inside your house. But if you revoke your - * gateway (and lock) PSK the outside sensor cannot be used for this anymore. Nor can it be changed - * in order to do it in the future. You can also use whitelisting to revoke your lost node.
- * This is an unlikely use case because there really is no reason to sign sensor values. If you for - * some reason want to obfuscate sensor data, encryption is a better alternative.
- * Configuration example for a motion sensor:
- * @code{.cpp} - * #define MY_SIGNING_SOFT - * #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 - * #define MY_SIGNING_REQUEST_SIGNATURES - * #include - * ... - * @endcode - * - * The gateway needs to be configured with a whitelist (and it has to have an entry for all nodes - * that send and/or require signed messages):
- * @code{.cpp} - * #define MY_SIGNING_SOFT - * #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 - * #define MY_SIGNING_REQUEST_SIGNATURES - * #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = MOTION_SENSOR_ID,.serial = {0x12,0x34,0x56,0x78,0x90,0x12,0x34,0x56,0x78}}} - * #include - * ... - * @endcode - - * @subsection MySigningkeyfob Keyfob for garage door opener - * - * Perhaps the most typical usecase for signed messages. Your keyfob should be totally locked down. - * If the garage door opener is secured (and it should be) it can be unlocked. That way, if you - * loose your keyfob, you can revoke the PSK in both the opener and your gateway, - * thus rendering the keyfob useless without having to replace your nodes. You can also use - * whitelisting to revoke your lost keyfob.
- * Configuration example for the keyfob (keyfob will only transmit to another node and not receive - * anything):
- * @code{.cpp} - * #define MY_SIGNING_ATSHA204 - * #include - * ... - * @endcode - * - * Configuration example for the door controller node (should require signing from anyone who wants - * to control it):
- * @code{.cpp} - * #define MY_SIGNING_SOFT - * #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 - * #define MY_SIGNING_REQUEST_SIGNATURES - * #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88}},{.nodeId = KEYFOB_ID,.serial = {}}} - * #include - * ... - * @endcode - * - * @subsection MySigningsketches Relevant sketches - * - * - @ref SecureActuator.ino - * - @ref SecurityPersonalizer.ino - * - * @section MySigningtechnical The technical stuff - * - * The following sequence diagram illustrate how messages are passed in a MySensors network with - * respect to signing: - * @image html MySigning/signingsequence.png - * - * None of this activity is “visible” to you (as the sensor sketch implementor). All you need to do - * is to set your preferences in your sketch and personalize accordingly. - * That is enough to enable protection from both Eve and Mallory in your network - * although if you do not also enable encryption, Eve can eavesdrop, but not do anything about, - * your messages (except possibly preventing them from arriving). - * - * How are the messages actually affected by the signing?
- * The following illustration shows what part of the message is signed, and where the signature is - * stored: - * @image html MySigning/signingillustrated1.png - * - * The first byte of the header is not covered by the signature, because in the network, this byte - * is used to track hops in the network and therefore might change if the message is passing a relay - * node. So it cannot be part of the signature, or the signature would be invalid when it arrives to - * its destination. The signature also carries a byte with a signing identifier to prevent false - * results from accidental mixing of incompatible signing backends in the network. Thus, the maximum - * size for a payload is 29-7 bytes. Larger payloads are not possible to sign at the moment. Another - * thing to consider is that the strength of the signature is inversely proportional to the payload - * size. - * - * As for the software backend, it turns out that the ATSHA does not do “vanilla” HMAC processing. - * Fortunately, Atmel has documented exactly how the circuit processes the data and hashes thus - * making it possible to generate signatures that are identical to signatures generated by the - * circuit. - * - * The signatures are calculates in the following way: - * @image html MySigning/signingillustrated2.png - * - * Exactly how this is done can be reviewed in the source for the software backend - * (MySigningAtsha204Soft.cpp) and the ATSHA204A - * datasheet - * . In the MySensors protocol, the following internal messagetypes handles signature - * requirements and nonce requests:
- * @ref I_SIGNING_PRESENTATION
- * @ref I_NONCE_REQUEST
- * @ref I_NONCE_RESPONSE
- * - * Also, the version field in the header has been reduced from 3 to 2 bits in order to fit a single - * bit to indicate that a message is signed. - * - * @section MySigninggrpbackground Background and concepts - * - * Suppose two participants, Alice and Bob, wants to exchange a message. Alice sends a message to - * Bob. In MySensors “language” Alice could be a gateway and Bob an actuator (light switch, - * electronic lock, etc). But to be generic, we will substitute the term “gateway” with Alice and a - * “node” with Bob (although the reverse relationship is also supported). - * - * Alice sends a message to Bob. This message can be heard by anyone who wants to listen (and also - * by anyone that is within “hearing” distance). Normally, this is perhaps not a big issue. Nothing - * Alice says to Bob may be secret or sensitive in any way. However, sometimes (or perhaps always) - * Bob want to be sure that the message Bob receives actually came from Alice. In cryptography, - * this is known as authenticity. Bob needs some way of determining that the message is - * authentic from Alice, when Bob receives it. This prevents an eavesdropper, Eve, to trick Bob into - * thinking it was Alice that sent a message Eve in fact transmitted. Bob also needs to know how to - * determine if the message has been repeated. Eve could record a message sent by Alice that Bob - * accepted and then send the same message again. Eve could also in some way prevent Bob from - * receiving the message and delay it in order to permit the message to arrive to Bob at a time Eve - * chooses, instead of Alice. Such an attack is known as a replay attack.
- * Authenticity permits Bob to determine if Alice is the true sender of a message. - * @image html MySigning/alicenfriends.png - * - * It can also be interesting for Bob to know that the message Alice sent has not been tampered with - * in any way. This is the integrity of the message. We now introduce Mallory, who could be - * intercepting the communication between Alice and Bob and replace some parts of the message but - * keeping the parts that authenticate the message. That way, Bob still trusts Alice to be the - * source, but the contents of the message was not the content Alice sent. Bob needs to be able to - * determine that the contents of the message was not altered after Alice sent it.
- * Mallory would in this case be a man-in-the-middle attacker.
- * Integrity permits Bob to verify that the messages received from Alice has not been - * tampered with.
- * This is achieved by adding a signature to the message, which Bob can inspect to validate - * that Alice is the author. - * @image html MySigning/alicenfriends2.png - * - * The signing scheme used, needs to address both these attack scenarios. Neither Eve nor Mallory - * must be permitted to interfere with the message exchange between Alice and Bob. - * - * The key challenge to implementing a secure signing scheme is to ensure that every signature is - * different, even if the message is not. If not, replay attacks would be very hard to - * prevent.
- * One way of doing this is to increment some counter on the sender side and include it in the - * signature. This is however predictable.
- * A better option would be to introduce a random number to the signature. That way, it is - * impossible to predict what the signature will be. The problem is, that also makes it impossible - * for the receiver (Bob) to verify that the signature is valid.
- * A solution to this is to let Bob generate the random number, keep it in memory and send it to - * Alice. Alice can then use the random number in the signature calculation and send the signed - * message back to Bob who can validate the signature with the random number used. - * This random number is in cryptography known as a - * nonce or - * salt. - * - * However, Mallory might be eavesdropping on the communication and snoop up the nonce in order to - * generate a new valid signature for a different message. To counter this, both Alice and Bob keep - * a secret that only they know. This secret is never transmitted over the air, - * nor is it revealed to anybody. This secret is known as a - * pre-shared key (PSK). - * - * If Eve or Mallory are really sophisticated, he/she might use a delayed replay attack. - * This can be done by allowing Bob to transmit a nonce to Alice. But when Alice transmits the - * uniquely signed message, Mallory prevents Bob from receiving it, to a point when Mallory - * decides Bob should receive it. An example of such an attack is described - * - * here.
- * This needs to be addressed as well, and one way of doing this is to have Bob keep track of time - * between a transmitted nonce and a signed message to verify. If Bob is asked for a nonce, Bob - * knows that a signed message is going to arrive “soon”. Bob can then decide that if the signed - * message does not arrive within a predefined timeframe, Bob throws away the generated nonce and - * thus makes it impossible to verify the message if it arrives late. - * - * The flow can be described like this: - * @image html MySigning/alicenbob.png - * The benefits for MySensors to support this are obvious. Nobody wants others to be able to control - * or manipulate any actuators in their home. - * - * @section MySigninggrphow How this is done - * - * There exist many forms of message signature solutions to combat Eve and Mallory.
- * Most of these solutions are quite complex in term of computations, so I elected to use an - * algorithm that an external circuit is able to process. This has the added benefit of protecting - * any keys and intermediate data used for calculating the signature so that even if someone were to - * actually steal a sensor and disassembled it, they would not be able to extract the keys and other - * information from the device.
- * A common scheme for message signing (authenticity and integrity) is implemented using - * HMAC which in - * combination with a strong hash function - * provides a very strong level of protection.
- * The Atmel ATSHA204A is a low-cost, - * low-voltage/current circuit that provides HMAC calculation capabilities with SHA256 hashing which - * is a (currently) virtually unbreakable combination. If SHA256 were to be hacked, a certain - * cryptocurrency would immediately be rendered - * worthless.
- * The ATSHA device also contain a random number generator (RNG) which enables the generation of a - * good nonce, as in, non-predictable.
- * As I acknowledge that some might not want to use an additional external circuit, I have also - * implemented a software version of the ATSHA device, capable of generating the same signatures as - * the ATSHA device does. Because it is pure-software however, it does not provide as good nonces - * (it uses the Arduino pseudo-random generator) - * and the HMAC key is stored in SW and is therefore readable if the memory is dumped. It also - * naturally claims more flash space due to the more complex software. But for indoor - * sensors/actuators this might be good enough for most people. - * - * @section MySigninggrpencryption Why encryption is not part of this - * - * Well, some could be uncomfortable with somebody being able to snoop temperatures, motion or the - * state changes of locks in the environment. - * Signing does not address these issues. Encryption is needed to prevent this.
- * It is my personal standpoint that encryption should not be part of the MySensors “protocol”. The - * reason is that a gateway and a node does not really care about messages being readable or not by - * “others”. It makes more sense that such guarantees are provided by the underlying transmission - * layer (RF solution in this case). It is the information transmitted over the air that needs to be - * secret (if user so desires). The “trust” level on the other hand needs to go all the way into the - * sketches (who might have different requirements of trust depending on the message participant), - * and for this reason, it is more important (and less complicated) to ensure authenticity and - * integrity at protocol-level as message contents is still readable throughout the protocol - * stack. But as soon as the message leaves the “stack” it can be scramble into “garbage” when - * transmitted over the air and then reassembled by a receiving node before being fed in “the clear” - * up the stack at the receiving end. - * - * There are methods and possibilities to provide encryption also in software, but if this is done, - * it is my recommendation that this is done after integrity- and authentication information has - * been provided to the message (if this is desired). Integrity and authentication is of course not - * mandatory and some might be happy with only having encryption to cover their need for security. - * I, however, have only focused on integrity and authenticity while at the same time - * keeping the current message routing mechanisms intact and therefore leave the matter of - * secrecy to be implemented in the “physical” transport layer. With the integrity and - * authenticity handled in the protocol it ought to be enough for a simple encryption - * (nonce-less %AES with a PSK for instance) on the message as it is sent to the RF backend. Atmel - * does provide such circuits as well but I have not investigated the matter further as it given the - * current size of the ethernet gateway sketch is close to the size limit on an Arduino Nano, so it - * will be difficult to fit this into some existing gateway designs.
- * Also it is worth to consider that the state of a lock can just as readily be determined by simply - * looking at the door in question or attempting to open it, so obfuscating this information will - * not necessarily deter an attacker in any way.
- * Nevertheless, I do acknowledge that people find the fact that all information is sent “in the - * clear” even if it require some technical effort for an intruder to obtain and inspect this - * information. So I do encourage the use of encrypting transport layers.
- * This is however not covered by this implementation.
- * This might change in the future as more powerful platforms emerge which permit more complex - * security schemes and better hardware acceleration. - */ -/** @}*/ - -/** - * @defgroup MySigninggrp MySigning - * @ingroup internals - * @{ - * - * @brief API declaration for MySigning signing backend - * - * @see MySigninggrpPub - */ -/** - * @file MySigning.h - * - * @brief API declaration for MySigning signing backend - */ -#ifndef MySigning_h -#define MySigning_h - -#include "MySensorsCore.h" -#include "drivers/ATSHA204/ATSHA204.h" - -#ifdef MY_SIGNING_NODE_WHITELISTING -typedef struct { - uint8_t nodeId; /**< @brief The ID of the node */ - uint8_t serial[SHA204_SERIAL_SZ]; /**< @brief Node specific serial number */ -} whitelist_entry_t; -#endif - -/** @brief Helper macro to determine the number of elements in a array */ -#define NUM_OF(x) (sizeof(x)/sizeof(x[0])) - -/** - * @brief Initializes signing infrastructure and associated backend. - * - * This function makes sure that the internal states of the signing infrastructure - * is set to a known initial state. - * \n@b Usage: This function should be called before any signing related operations take place. - */ -void signerInit(void); - -/** - * @brief Does signing specific presentation for a node. - * - * This function makes sure any signing related presentation info is shared with the other part. - * The presentation of the gateways signing preferences is done in @ref signerProcessInternal(). - * \n@b Usage: This function should be called by the presentation routine of the MySensors library. - * You only need to call this directly from a sketch to set up a node to node signed message exchange. - * If you do call this directly from a sketch, and you at some point change your sketch to go from - * requiring signing to not requiring signatures, you need to present this change to the node at least - * once, so it can update its requirements tables accordingly. Or it will keep believing that this node - * require signatures and attempt to send signed messages to it. - * - * @param msg Message buffer to use. - * @param destination Node ID of the destination. - */ -void signerPresentation(MyMessage &msg, uint8_t destination); - -/** - * @brief Manages internal signing message handshaking. - * - * This function takes care of signing related message handshaking such as nonce exchange. - * \n@b Usage: This function should be called by the incoming message handler before any further message - * processing is performed on internal messages. This function should only be called for @ref C_INTERNAL class - * messages. - * - * @param msg Message buffer to process. - * @returns @c true if caller should stop further message processing. - */ -bool signerProcessInternal(MyMessage &msg); - -/** - * @brief Check timeout of verification session. - * - * Nonce will be purged if it takes too long for a signed message to be sent to the receiver. - * \n@b Usage: This function should be called on regular intervals, typically within some process loop. - * - * @returns @c true if session is still valid. - */ -bool signerCheckTimer(void); - -/** - * @brief Get nonce from provided message and store for signing operations. - * - * Returns @c false if subsystem is busy processing an ongoing signing operation.
- * Returns @c false if signing identifier found in message is not supported by the used backend.
- * If successful, this marks the start of a signing operation at the sending side so - * implementation is expected to do any necessary initializations within this call. - * \n@b Usage: This function is typically called as action when receiving a @ref I_NONCE_RESPONSE - * message. - * - * @param msg The message to get the nonce from. - * @returns @c true if successful, else @c false. - */ -bool signerPutNonce(MyMessage &msg); - -/** - * @brief Signs provided message. All remaining space in message payload buffer is used for - * signing identifier and signature. - * - * Nonce used for signature calculation is the one generated previously within @ref signerProcessInternal().
- * Nonce will be cleared when this function is called to prevent re-use of nonce.
- * Returns @c false if subsystem is busy processing an ongoing signing operation.
- * Returns @c false if not two bytes or more of free payload space is left in provided message.
- * This ends a signing operation at the sending side so implementation is expected to do any - * deinitializations and enter a power saving state within this call. - * \n@b Usage: This function is typically called as action when receiving a @ref I_NONCE_RESPONSE - * message and after @ref signerPutNonce() has successfully been executed. - * - * @param msg The message to sign. - * @returns @c true if successful, else @c false. -*/ -bool signerSignMsg(MyMessage &msg); - -/** - * @brief Verifies signature in provided message. - * - * Nonce used for verification is the one previously set using @ref signerPutNonce().
- * Nonce will be cleared when this function is called to prevent re-use of nonce.
- * Returns @c false if subsystem is busy processing an ongoing signing operation.
- * Returns @c false if signing identifier found in message is not supported by the used backend.
- * This ends a signing operation at the receiving side so implementation is expected to do any - * deinitializations and enter a power saving state within this call. - * \n@b Usage: This function is typically called when receiving a message that is flagged as signed - * and @ref MY_SIGNING_REQUEST_SIGNATURES is activated. - * - * @param msg The message to verify. - * @returns @c true if successful, else @c false. - */ -bool signerVerifyMsg(MyMessage &msg); - -/** - * @brief Do a timing neutral memory comparison. - * - * The function behaves similar to memcmp with the difference that it will - * always use the same number of instructions for a given number of bytes, - * no matter how the two buffers differ and the response is either 0 or -1. - * - * @param a First buffer for comparison. - * @param b Second buffer for comparison. - * @param sz The number of bytes to compare. - * @returns 0 if buffers match, -1 if they do not. - */ -int signerMemcmp(const void* a, const void* b, size_t sz); - -#endif -/** @}*/ - -/** - * @defgroup MySigningDebugMessages Signing related debug messages - * @ingroup MySigninggrpPub - * @{ - * - * @brief Explanation of the abstract signing related debug messages - * - * MySigning-related log messages, format: [!]SYSTEM:SUB SYSTEM:MESSAGE - * - [!] Exclamation mark is prepended in case of error or warning - * - SYSTEM: - * - SGN messages emitted by MySigning - * - SUB SYSTEMS: - * - SGN:INI from @ref signerInit - * - SGN:PER from @ref signerInit - * - SGN:PRE from @ref signerPresentation - * - SGN:SGN from @ref signerSignMsg - * - SGN:VER from @ref signerVerifyMsg - * - SGN:SKP from @ref signerSignMsg or @ref signerVerifyMsg (skipSign) - * - SGN:NCE from @ref signerProcessInternal (signerInternalProcessNonceRequest) - * - SGN:BND from the signing backends - * - * MySigning debug log messages: - * - * |E| SYS | SUB | Message | Comment - * |-|-----|-----|--------------------------|---------------------------------------------------------------------------- - * | | SGN | INI | BND OK | Backend has initialized ok - * |!| SGN | INI | BND FAIL | Backend has not initialized ok - * | | SGN | PER | OK | Personalization data is ok - * |!| SGN | PER | TAMPERED | Personalization data has been tampered - * | | SGN | PRE | SGN REQ | Signing required - * | | SGN | PRE | SGN REQ,TO='node' | Tell 'node' that we require signing - * | | SGN | PRE | SGN REQ,FROM='node' | Node 'node' require signing - * | | SGN | PRE | SGN NREQ | Signing not required - * | | SGN | PRE | SGN REQ,TO='node' | Tell 'node' that we do not require signing - * | | SGN | PRE | SGN NREQ,FROM='node' | Node 'node' does not require signing - * |!| SGN | PRE | SGN NREQ,FROM='node' REJ | Node 'node' does not require signing but used to (requirement remain unchanged) - * | | SGN | PRE | WHI REQ | Whitelisting required - * | | SGN | PRE | WHI REQ,TO='node' | Tell 'node' that we require whitelisting - * | | SGN | PRE | WHI REQ,FROM='node' | Node 'node' require whitelisting - * | | SGN | PRE | WHI NREQ | Whitelisting not required - * | | SGN | PRE | WHI NREQ,TO='node' | Tell 'node' that we do not require whitelisting - * | | SGN | PRE | WHI NREQ,FROM='node' | Node 'node' does not require whitelisting - * |!| SGN | PRE | WHI NREQ,FROM='node' REJ | Node 'node' does not require whitelisting but used to (requirement remain unchanged) - * | | SGN | PRE | XMT,TO='node' | Presentation data transmitted to 'node' - * |!| SGN | PRE | XMT,TO='node' FAIL | Presentation data not properly transmitted to 'node' - * | | SGN | PRE | WAIT GW | Waiting for gateway presentation data - * |!| SGN | PRE | VER='version' | Presentation version 'version' is not supported - * | | SGN | PRE | NSUP | Received signing presentation but signing is not supported - * | | SGN | PRE | NSUP,TO='node' | Informing 'node' that we do not support signing - * | | SGN | SGN | NCE REQ,TO='node' | Nonce request transmitted to 'node' - * |!| SGN | SGN | NCE REQ,TO='node' FAIL | Nonce request not properly transmitted to 'node' - * |!| SGN | SGN | NCE TMO | Timeout waiting for nonce - * | | SGN | SGN | SGN | Message signed - * |!| SGN | SGN | SGN FAIL | Message failed to be signed - * | | SGN | SGN | NREQ='node' | 'node' does not require signed messages - * | | SGN | SGN | 'sender'!='us' NUS | Will not sign because 'sender' is not 'us' (repeater) - * |!| SGN | SGN | STATE | Security system in a invalid state (personalization data tampered) - * |!| SGN | VER | NSG | Message was not signed, but it should have been - * |!| SGN | VER | FAIL | Verification failed - * | | SGN | VER | OK | Verification succeeded - * | | SGN | VER | LEFT='number' | 'number' of failed verifications left in a row before node is locked - * |!| SGN | VER | STATE | Security system in a invalid state (personalization data tampered) - * | | SGN | SKP | MSG CMD='cmd',TYPE='type'| Message with command 'cmd' and type 'type' does not need to be signed - * | | SGN | SKP | ECHO CMD='cmd',TYPE='type'| ECHO messages does not need to be signed - * | | SGN | NCE | LEFT='number' | 'number' of nonce requests between successful verifications left before node is locked - * | | SGN | NCE | XMT,TO='node' | Nonce data transmitted to 'node' - * |!| SGN | NCE | XMT,TO='node' FAIL | Nonce data not properly transmitted to 'node' - * |!| SGN | NCE | GEN | Failed to generate nonce - * | | SGN | NCE | NSUP (DROPPED) | Ignored nonce/request for nonce (signing not supported) - * | | SGN | NCE | FROM='node' | Received nonce from 'node' - * | | SGN | NCE | 'sender'!='dst' (DROPPED)| Ignoring nonce as it did not come from the designation of the message to sign - * |!| SGN | BND | INIT FAIL | Failed to initialize signing backend - * |!| SGN | BND | PWD<8 | Signing password too short - * |!| SGN | BND | PER | Backend not personalized - * |!| SGN | BND | SER | Could not get device unique serial from backend - * |!| SGN | BND | TMR | Backend timed out - * |!| SGN | BND | SIG,SIZE,'message'>'max' | Refusing to sign 'message' because it is bigger than 'max' allowed size - * | | SGN | BND | SIG WHI,ID='id' | Salting message with our 'id' - * | | SGN | BND | SIG WHI,SERIAL='serial' | Salting message with our 'serial' - * |!| SGN | BND | VER ONGOING | Verification failed, no ongoing session - * |!| SGN | BND | VER,IDENT='identifier' | Verification failed, 'identifier' is unknown - * | | SGN | BND | VER WHI,ID='sender' | 'sender' found in whitelist - * | | SGN | BND | VER WHI,SERIAL='serial' | Expecting 'serial' for this sender - * |!| SGN | BND | VER WHI,ID='id' MISSING | 'id' not found in whitelist - * | | SGN | BND | NONCE='nonce' | Calculating signature using 'nonce' - * | | SGN | BND | HMAC='hmac' | Calculated signature is 'hmac' - */ -/** @}*/ - -/** - * @defgroup MySigningTroubleshootinggrp Signing troubleshooting - * @ingroup MySigninggrpPub - * @{ - * - * @brief Typical signing related failure cases and how to solve them - * - * @section MySigningTroubleshootingSymptoms Symptoms and solutions - * - * The first thing to do if you suspect signing is causing problems, is to enable the verbose debug - * flag for the signing backend. @see MY_DEBUG_VERBOSE_SIGNING - * - * If you are having trouble getting signing to work, please see the following troubleshooting tips. - * - * @subsection MySigningTroubleshootingSymptomStFail Signing fails and logs show st=fail on transmissions - * - * This is actually not a signing problem, although often st=fail becomes st=ok when signing is disabled. - * This is by far the most commonly reported problem with signing, but the problems is not with signing, - * it is with radio performance.
- * This is a typical log which might look like a signing related issue but isn't: - * @code{.unparsed} - * 0;255;3;0;9;Skipping security for command 3 type 16 - * 0;255;3;0;9;read: 3-3-0 s=255,c=3,t=16,pt=0,l=0,sg=0: - * 0;255;3;0;9;Signing backend: ATSHA204Soft - * 0;255;3;0;9;SHA256: 86DEAE1DAF50D577A4E2262B33ABF9DEE05DD8FAF84F94F50900000000000000 - * 0;255;3;0;9;Skipping security for command 3 type 17 - * 0;255;3;0;9;send: 0-0-3-3 s=255,c=3,t=17,pt=6,l=25,sg=0,st=fail:86DEAE1DAF50D577A4E2262B33ABF9DEE05DD8FAF84F94F509 - * 0;255;3;0;9;Failed to transmit nonce! - * 0;255;3;0;9;Message is not signed, but it should have been! - * 0;255;3;0;9;verify fail - * @endcode - * - * The reason for this is that when signing is used, the messages transmitted become relatively large.
- * Because of this, the message is more sensitive to noise, and the chance for a message to get scrambled - * increase with the message size. Please refer to the troubleshooting section at the MySensors forum for - * information on how to improve radio performance.
- * This is a good place to start: https://forum.mysensors.org/topic/666/debug-faq-and-how-ask-for-help - * - * @subsection MySigningTroubleshootingSymptomNonce Failed to generate nonce - * - * The signing backend failed to generate the nonce needed to sign a message. This indicate a hardware - * problem. Please post the debug info on the forum together with a description of your hardware setup. - * - * @subsection MySigningTroubleshootingSymptomSign Failed to sign message - * - * The signing backend failed to sign the message. Typically this happens if your message is so large, - * that there is no room left in the buffer to store a signature. - * - * @subsection MySigningTroubleshootingSymptomWrongSource Nonce did not come from the destination (XX) of the message to be signed! It came from YY - * - * This should not really happen. The reason for this message is that the signing backend is only capable - * of handling one signed message session at any time. If for some reason multiple nodes send a nonce message to - * the same node, only the nonce from a node that is the destination of the current message signing session will be - * accepted. Any other nonces will be dropped. This should not happen as no node should send a nonce unless asked to, - * and a node will only ask for a nonce to one destination for every signing session.
- * If you see this message, please post the debugging details on the MySensors forum so it can be investigated further - * together with a description of your setup. - * - * @subsection MySigningTroubleshootingSymptomNotSigned Message is not signed, but it should have been - * - * A node has failed to comply with the signing preferences of this node. Check that the node has received a - * signing presentation message from this node. This is automatically transmitted to gateways. For other nodes, - * you need to transmit the presentation from the sketch. @see signerPresentation - * - * @subsection MySigningTroubleshootingSymptomNotSignedGeneral "Messages do not appear to be signed but I think they should be..." - * - * Make sure you have enabled the flag to require signatures to require signatures and have enabled one of the signing - * backends. @see MY_SIGNING_REQUEST_SIGNATURES @see MY_SIGNING_ATSHA204 @see MY_SIGNING_SOFT - * - * @subsection MySigningTroubleshootingSymptomNotWorkingWhitelisting Signature verification failed! - * - * Make sure both source and destination of the signed message has undergone @ref personalization with the same HMAC key.
- * Also, if whitelisting is used, make sure the proper serial is paired with the proper node ID at the destination. - * Whitelisting preferences are communicated with the signing presentation (done automatically from nodes to gateway but - * has to be explicitly done by sketch for node to node communication). @see signerPresentation - * - * @subsection MySigningTroubleshootingSymptomStTampered Signing backend reports tampered even after personalization - * - * The signing backend validates that the secure elements in EEPROM remain unmodified after personalization using a checksum. If the check fails, - * the backend reports - * @code - * !SGN:PER:Tampered - * @endcode - * This usually indicate that the sketch has modified the secure elements in EEPROM, but if you experience this even after a node is freshly - * personalized on a atmega device, it could be that the EESAVE fuse bit is not set which mean that the EEPROM is erased when a new firmware is flashed. - * You will need to enable the EESAVE bit in order to have the security personalization persist in the node. - */ -/** @}*/ diff --git a/lib/MySensors/core/MySigningAtsha204.cpp b/lib/MySensors/core/MySigningAtsha204.cpp deleted file mode 100644 index a82075ac..00000000 --- a/lib/MySensors/core/MySigningAtsha204.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * Signing support created by Patrick "Anticimex" Fallberg - * ATSHA204 signing backend. The Atmel ATSHA204 offers true random number generation and - * HMAC-SHA256 authentication with a readout-protected key. - * - */ - -#include "MySigning.h" -#include "MyHelperFunctions.h" - -#ifdef MY_SIGNING_ATSHA204 -#define SIGNING_IDENTIFIER (1) //HMAC-SHA256 - -#if defined(MY_DEBUG_VERBOSE_SIGNING) -#define SIGN_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) -#else -#define SIGN_DEBUG(x,...) -#endif - -static unsigned long _signing_timestamp; -static bool _signing_verification_ongoing = false; -static uint8_t _signing_verifying_nonce[32+9+1]; -static uint8_t _signing_signing_nonce[32+9+1]; -static uint8_t _signing_temp_message[SHA_MSG_SIZE]; -static uint8_t _signing_rx_buffer[SHA204_RSP_SIZE_MAX]; -static uint8_t _signing_tx_buffer[SHA204_CMD_SIZE_MAX]; -static uint8_t* const _signing_hmac = &_signing_rx_buffer[SHA204_BUFFER_POS_DATA]; -static uint8_t _signing_node_serial_info[9]; -#ifdef MY_SIGNING_NODE_WHITELISTING -static const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING; -#endif - -static bool init_ok = false; - -static void signerCalculateSignature(MyMessage &msg, bool signing); -static uint8_t* signerAtsha204AHmac(const uint8_t* nonce, const uint8_t* data); -static uint8_t* signerSha256(const uint8_t* data, size_t sz); - -bool signerAtsha204Init(void) -{ - init_ok = true; - atsha204_init(MY_SIGNING_ATSHA204_PIN); - - (void)atsha204_wakeup(_signing_temp_message); - // Read the configuration lock flag to determine if device is personalized or not - if (atsha204_read(_signing_tx_buffer, _signing_rx_buffer, - SHA204_ZONE_CONFIG, 0x15<<2) != SHA204_SUCCESS) { - SIGN_DEBUG(PSTR("!SGN:BND:INIT FAIL\n")); //Could not read ATSHA204A lock config - init_ok = false; - } else if (_signing_rx_buffer[SHA204_BUFFER_POS_DATA+3] != 0x00) { - SIGN_DEBUG(PSTR("!SGN:BND:PER\n")); //ATSHA204A not personalized - init_ok = false; - } - if (init_ok) { - // Get and cache the serial of the ATSHA204A - if (atsha204_getSerialNumber(_signing_node_serial_info) != SHA204_SUCCESS) { - SIGN_DEBUG(PSTR("!SGN:BND:SER\n")); //Could not get ATSHA204A serial - init_ok = false; - } - } - return init_ok; -} - -bool signerAtsha204CheckTimer(void) -{ - if (!init_ok) { - return false; - } - if (_signing_verification_ongoing) { - unsigned long time_now = hwMillis(); - // If timestamp is taken so late a rollover can take place during the timeout, - // offset both timestamp and current time to make sure no rollover takes place during the - // timeout - if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < _signing_timestamp) { - _signing_timestamp += MY_VERIFICATION_TIMEOUT_MS; - time_now += MY_VERIFICATION_TIMEOUT_MS; - } - if (time_now > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { - SIGN_DEBUG(PSTR("!SGN:BND:TMR\n")); //Verification timeout - // Purge nonce - memset(_signing_signing_nonce, 0xAA, 32); - memset(_signing_verifying_nonce, 0xAA, 32); - _signing_verification_ongoing = false; - return false; - } - } - return true; -} - -bool signerAtsha204GetNonce(MyMessage &msg) -{ - if (!init_ok) { - return false; - } - - // We used a basic whitening technique that XORs each byte in a 32byte random value with current - // hwMillis() counter. This 32-byte random value is then hashed (SHA256) to produce the resulting - // nonce - (void)atsha204_wakeup(_signing_temp_message); - if (atsha204_execute(SHA204_RANDOM, RANDOM_SEED_UPDATE, 0, 0, NULL, - RANDOM_COUNT, _signing_tx_buffer, RANDOM_RSP_SIZE, _signing_rx_buffer) != - SHA204_SUCCESS) { - return false; - } - for (int i = 0; i < 32; i++) { - _signing_verifying_nonce[i] = _signing_rx_buffer[SHA204_BUFFER_POS_DATA+i] ^ (hwMillis()&0xFF); - } - (void)memcpy((void *)_signing_verifying_nonce, (const void *)signerSha256(_signing_verifying_nonce, - 32), - min((uint8_t)MAX_PAYLOAD_SIZE, 32u)); - - // We just idle the chip now since we expect to use it soon when the signed message arrives - atsha204_idle(); - - if (MAX_PAYLOAD_SIZE < 32) { - // We set the part of the 32-byte nonce that does not fit into a message to 0xAA - (void)memset((void *)&_signing_verifying_nonce[MAX_PAYLOAD_SIZE], 0xAA, 32u - MAX_PAYLOAD_SIZE); - } - - // Transfer the first part of the nonce to the message - msg.set(_signing_verifying_nonce, min((uint8_t)MAX_PAYLOAD_SIZE, 32u)); - _signing_verification_ongoing = true; - _signing_timestamp = hwMillis(); // Set timestamp to determine when to purge nonce - return true; -} - -void signerAtsha204PutNonce(MyMessage &msg) -{ - if (!init_ok) { - return; - } - - (void)memcpy((void *)_signing_signing_nonce, (const void *)msg.getCustom(), - min((uint8_t)MAX_PAYLOAD_SIZE, 32u)); - if (MAX_PAYLOAD_SIZE < 32u) { - // We set the part of the 32-byte nonce that does not fit into a message to 0xAA - (void)memset((void *)&_signing_signing_nonce[MAX_PAYLOAD_SIZE], 0xAA, 32u - MAX_PAYLOAD_SIZE); - } -} - -bool signerAtsha204SignMsg(MyMessage &msg) -{ - // If we cannot fit any signature in the message, refuse to sign it - if (msg.getLength() > MAX_PAYLOAD_SIZE - 2) { - SIGN_DEBUG(PSTR("!SGN:BND:SIG,SIZE,%" PRIu8 ">%" PRIu8 "\n"), msg.getLength(), - MAX_PAYLOAD_SIZE - 2); //Message too large - return false; - } - - // Calculate signature of message - msg.setSigned(true); // make sure signing flag is set before signature is calculated - signerCalculateSignature(msg, true); - -#if defined(MY_SIGNING_NODE_WHITELISTING) - if (DO_WHITELIST(msg.destination)) { - // Salt the signature with the senders nodeId and the unique serial of the ATSHA device - // We can reuse the nonce buffer now since it is no longer needed - memcpy(_signing_signing_nonce, _signing_hmac, 32); - _signing_signing_nonce[32] = msg.getSender(); - memcpy(&_signing_signing_nonce[33], _signing_node_serial_info, 9); - // We can 'void' sha256 because the hash is already put in the correct place - (void)signerSha256(_signing_signing_nonce, 32+1+9); - SIGN_DEBUG(PSTR("SGN:BND:SIG WHI,ID=%" PRIu8 "\n"), msg.getSender()); -#ifdef MY_DEBUG_VERBOSE_SIGNING - hwDebugBuf2Str(_signing_node_serial_info, 9); - SIGN_DEBUG(PSTR("SGN:BND:SIG WHI,SERIAL=%s\n"), hwDebugPrintStr); -#endif - } -#endif - - // Put device back to sleep - atsha204_sleep(); - - // Overwrite the first byte in the signature with the signing identifier - _signing_hmac[0] = SIGNING_IDENTIFIER; - - // Transfer as much signature data as the remaining space in the message permits - (void)memcpy((void *)&msg.data[msg.getLength()], (const void *)_signing_hmac, - min(MAX_PAYLOAD_SIZE - msg.getLength(), 32)); - - return true; -} - -bool signerAtsha204VerifyMsg(MyMessage &msg) -{ - if (!_signing_verification_ongoing) { - SIGN_DEBUG(PSTR("!SGN:BND:VER ONGOING\n")); - return false; - } else { - // Make sure we have not expired - if (!signerCheckTimer()) { - return false; - } - - _signing_verification_ongoing = false; - - if (msg.data[msg.getLength()] != SIGNING_IDENTIFIER) { - SIGN_DEBUG(PSTR("!SGN:BND:VER,IDENT=%" PRIu8 "\n"), msg.data[msg.getLength()]); - return false; - } - - signerCalculateSignature(msg, false); // Get signature of message - -#ifdef MY_SIGNING_NODE_WHITELISTING - // Look up the senders nodeId in our whitelist and salt the signature with that data - size_t j; - for (j=0; j < NUM_OF(_signing_whitelist); j++) { - if (_signing_whitelist[j].nodeId == msg.getSender()) { - // We can reuse the nonce buffer now since it is no longer needed - memcpy(_signing_verifying_nonce, _signing_hmac, 32); - _signing_verifying_nonce[32] = msg.getSender(); - memcpy(&_signing_verifying_nonce[33], _signing_whitelist[j].serial, 9); - // We can 'void' sha256 because the hash is already put in the correct place - (void)signerSha256(_signing_verifying_nonce, 32+1+9); - SIGN_DEBUG(PSTR("SGN:BND:VER WHI,ID=%" PRIu8 "\n"), msg.getSender()); -#ifdef MY_DEBUG_VERBOSE_SIGNING - hwDebugBuf2Str(_signing_whitelist[j].serial, 9); - SIGN_DEBUG(PSTR("SGN:BND:VER WHI,SERIAL=%s\n"), hwDebugPrintStr); -#endif - break; - } - } - if (j == NUM_OF(_signing_whitelist)) { - SIGN_DEBUG(PSTR("!SGN:BND:VER WHI,ID=%" PRIu8 " MISSING\n"), msg.getSender()); - // Put device back to sleep - atsha204_sleep(); - return false; - } -#endif - - // Put device back to sleep - atsha204_sleep(); - - // Overwrite the first byte in the signature with the signing identifier - _signing_hmac[0] = SIGNING_IDENTIFIER; - - // Compare the calculated signature with the provided signature - if (signerMemcmp(&msg.data[msg.getLength()], _signing_hmac, - min(MAX_PAYLOAD_SIZE - msg.getLength(), 32))) { - return false; - } else { - return true; - } - } -} - -// Helper to calculate signature of msg (returned in _signing_rx_buffer[SHA204_BUFFER_POS_DATA]) -// (=_signing_hmac) -static void signerCalculateSignature(MyMessage &msg, bool signing) -{ - // Signature is calculated on everything expect the first byte in the header - uint16_t bytes_left = msg.getLength()+HEADER_SIZE-1; - int16_t current_pos = 1-(int16_t)HEADER_SIZE; // Start at the second byte in the header - uint8_t* nonce = signing ? _signing_signing_nonce : _signing_verifying_nonce; - -#ifdef MY_DEBUG_VERBOSE_SIGNING - hwDebugBuf2Str(nonce, 32); - SIGN_DEBUG(PSTR("SGN:BND:NONCE=%s\n"), hwDebugPrintStr); -#endif - - while (bytes_left) { - uint16_t bytes_to_include = min(bytes_left, 32); - - (void)atsha204_wakeup(_signing_temp_message); // Issue wakeup to reset watchdog - memset(_signing_temp_message, 0, 32); - memcpy(_signing_temp_message, (uint8_t*)&msg.data[current_pos], bytes_to_include); - - // We can 'void' signerAtsha204AHmac because the HMAC is already put in the correct place - (void)signerAtsha204AHmac(nonce, _signing_temp_message); - // Purge nonce when used - memset(nonce, 0xAA, 32); - - bytes_left -= bytes_to_include; - current_pos += bytes_to_include; - - if (bytes_left > 0) { - // We will do another pass, use current HMAC as nonce for the next HMAC - memcpy(nonce, _signing_hmac, 32); - atsha204_idle(); // Idle the chip to allow the wakeup call to reset the watchdog - } - } -#ifdef MY_DEBUG_VERBOSE_SIGNING - hwDebugBuf2Str(_signing_hmac, 32); - SIGN_DEBUG(PSTR("SGN:BND:HMAC=%s\n"), hwDebugPrintStr); -#endif -} - -// Helper to calculate a ATSHA204A specific HMAC-SHA256 using provided 32 byte nonce and data -// (zero padded to 32 bytes) -// The pointer to the HMAC is returned, but the HMAC is also stored in -// _signing_rx_buffer[SHA204_BUFFER_POS_DATA] (=_signing_hmac) -static uint8_t* signerAtsha204AHmac(const uint8_t* nonce, const uint8_t* data) -{ - // Program the data to sign into the ATSHA204 - (void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, - (uint8_t*)data, - WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer); - - // Program the nonce to use for the signature (has to be done just before GENDIG - // due to chip limitations) - (void)atsha204_execute(SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0, 32, (uint8_t*)nonce, - NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, - _signing_rx_buffer); - - // Generate digest of data and nonce - (void)atsha204_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL, - GENDIG_COUNT_DATA, _signing_tx_buffer, GENDIG_RSP_SIZE, - _signing_rx_buffer); - - // Calculate HMAC of message+nonce digest and secret key - (void)atsha204_execute(SHA204_HMAC, HMAC_MODE_SOURCE_FLAG_MATCH, 0, 0, NULL, - HMAC_COUNT, _signing_tx_buffer, HMAC_RSP_SIZE, _signing_rx_buffer); - return &_signing_rx_buffer[SHA204_BUFFER_POS_DATA]; -} - -// Helper to calculate a generic SHA256 digest of provided buffer (only supports one block) -// The pointer to the hash is returned, but the hash is also stored in -// _signing_rx_buffer[SHA204_BUFFER_POS_DATA]) -static uint8_t* signerSha256(const uint8_t* data, size_t sz) -{ - // Initiate SHA256 calculator - (void)atsha204_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL, - SHA_COUNT_SHORT, _signing_tx_buffer, SHA_RSP_SIZE_SHORT, - _signing_rx_buffer); - - // Calculate a hash - memset(_signing_temp_message, 0x00, SHA_MSG_SIZE); - memcpy(_signing_temp_message, data, sz); - _signing_temp_message[sz] = 0x80; - // Write length data to the last bytes - _signing_temp_message[SHA_MSG_SIZE-2] = (sz >> 5); - _signing_temp_message[SHA_MSG_SIZE-1] = (sz << 3); - (void)atsha204_execute(SHA204_SHA, SHA_CALC, 0, SHA_MSG_SIZE, _signing_temp_message, - SHA_COUNT_LONG, _signing_tx_buffer, SHA_RSP_SIZE_LONG, _signing_rx_buffer); - return &_signing_rx_buffer[SHA204_BUFFER_POS_DATA]; -} -#endif //MY_SIGNING_ATSHA204 diff --git a/lib/MySensors/core/MySigningAtsha204Soft.cpp b/lib/MySensors/core/MySigningAtsha204Soft.cpp deleted file mode 100644 index 7515ba6d..00000000 --- a/lib/MySensors/core/MySigningAtsha204Soft.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * Signing support created by Patrick "Anticimex" Fallberg - * ATSHA204 emulated signing backend. The emulated ATSHA204 implementation offers pseudo random - * number generation and HMAC-SHA256 authentication compatible with a "physical" ATSHA204. - * NOTE: Key is stored in clear text in the Arduino firmware. Therefore, the use of this back-end - * could compromise the key used in the signed message infrastructure if device is lost and its - * memory dumped. - * - */ - -#include "MySigning.h" -#include "MyHelperFunctions.h" - -#ifdef MY_SIGNING_SOFT -#define SIGNING_IDENTIFIER (1) //HMAC-SHA256 - -#if defined(MY_DEBUG_VERBOSE_SIGNING) -#define SIGN_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) -#else -#define SIGN_DEBUG(x,...) -#endif - -static unsigned long _signing_timestamp; -static bool _signing_verification_ongoing = false; -static bool _signing_init_ok = false; -static uint8_t _signing_verifying_nonce[32+9+1]; -static uint8_t _signing_nonce[32+9+1]; -static uint8_t _signing_hmac_key[SIZE_SIGNING_SOFT_HMAC_KEY]; -static uint8_t _signing_hmac[32]; -static uint8_t _signing_node_serial_info[SIZE_SIGNING_SOFT_SERIAL]; - -#ifdef MY_SIGNING_NODE_WHITELISTING -static const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING; -#endif - -static void signerCalculateSignature(MyMessage &msg, const bool signing); -static void signerAtsha204AHmac(uint8_t *dest, const uint8_t *nonce, const uint8_t *data); - -bool signerAtsha204SoftInit(void) -{ - _signing_init_ok = true; - // initialize pseudo-RNG - hwRandomNumberInit(); - // Set secrets -#ifdef MY_SIGNING_SIMPLE_PASSWD - if (strnlen(MY_SIGNING_SIMPLE_PASSWD, 32) < 8) { - SIGN_DEBUG(PSTR("!SGN:BND:PWD<8\n")); //Password is too short to be acceptable - _signing_init_ok = false; - } else { - (void)memset((void *)_signing_hmac_key, 0x00, sizeof(_signing_hmac_key)); - (void)memcpy((void *)_signing_hmac_key, MY_SIGNING_SIMPLE_PASSWD, strnlen(MY_SIGNING_SIMPLE_PASSWD, - 32)); - (void)memset((void *)_signing_node_serial_info, 0x00, sizeof(_signing_node_serial_info)); - (void)memcpy((void *)_signing_node_serial_info, MY_SIGNING_SIMPLE_PASSWD, - strnlen(MY_SIGNING_SIMPLE_PASSWD, 8)); - _signing_node_serial_info[8] = getNodeId(); - } -#else - hwReadConfigBlock((void *)_signing_hmac_key, (void *)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, - SIZE_SIGNING_SOFT_HMAC_KEY); - hwReadConfigBlock((void *)_signing_node_serial_info, (void *)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, - SIZE_SIGNING_SOFT_SERIAL); -#endif - - uint16_t chk = 0; - for (uint8_t i = 0; i < SIZE_SIGNING_SOFT_SERIAL; i++) { - chk += _signing_node_serial_info[i]; - } - if (chk==SIZE_SIGNING_SOFT_SERIAL * - 0xFF) { // test if == { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } - unique_id_t uniqueID; - // There is no serial, attempt to get unique ID for serial instead - if (hwUniqueID(&uniqueID)) { - // There is a unique serial, use that - (void)memcpy((void *)_signing_node_serial_info, (const void *)uniqueID, SIZE_SIGNING_SOFT_SERIAL); - } - } - return _signing_init_ok; -} - -bool signerAtsha204SoftCheckTimer(void) -{ - if (!_signing_init_ok) { - return false; - } - if (_signing_verification_ongoing) { - unsigned long time_now = hwMillis(); - // If timestamp is taken so late a rollover can take place during the timeout, - // offset both timestamp and current time to make sure no rollover takes place during the - // timeout - if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < _signing_timestamp) { - _signing_timestamp += MY_VERIFICATION_TIMEOUT_MS; - time_now += MY_VERIFICATION_TIMEOUT_MS; - } - if (time_now > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { - SIGN_DEBUG(PSTR("!SGN:BND:TMR\n")); //Verification timeout - // Purge nonce - (void)memset((void *)_signing_nonce, 0xAA, sizeof(_signing_nonce)); - (void)memset((void *)_signing_verifying_nonce, 0xAA, sizeof(_signing_verifying_nonce)); - _signing_verification_ongoing = false; - return false; - } - } - return true; -} - -bool signerAtsha204SoftGetNonce(MyMessage &msg) -{ - if (!_signing_init_ok) { - return false; - } - -#ifdef MY_HW_HAS_GETENTROPY - // Try to get MAX_PAYLOAD_SIZE random bytes - while (hwGetentropy(&_signing_verifying_nonce, MAX_PAYLOAD_SIZE) != MAX_PAYLOAD_SIZE); -#else - // We used a basic whitening technique that XORs a random byte with the current hwMillis() counter - // and then the byte is hashed (SHA256) to produce the resulting nonce - uint8_t randBuffer[32]; - for (uint8_t i = 0; i < sizeof(randBuffer); i++) { - randBuffer[i] = random(256) ^ (hwMillis() & 0xFF); - } - SHA256(_signing_verifying_nonce, randBuffer, sizeof(randBuffer)); -#endif - - if (MAX_PAYLOAD_SIZE < 32) { - // We set the part of the 32-byte nonce that does not fit into a message to 0xAA - (void)memset((void *)&_signing_verifying_nonce[MAX_PAYLOAD_SIZE], 0xAA, 32u - MAX_PAYLOAD_SIZE); - } - - // Transfer the first part of the nonce to the message - msg.set(_signing_verifying_nonce, MIN((uint8_t)MAX_PAYLOAD_SIZE, (uint8_t)32)); - _signing_verification_ongoing = true; - _signing_timestamp = hwMillis(); // Set timestamp to determine when to purge nonce - // Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover) - // Note that if message is "too" quick, and arrives before turnover, it will be rejected - // but this is consider such a rare case that it is accepted and rejects are 'safe' - if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < hwMillis()) { - _signing_timestamp = 0; - } - return true; -} - -void signerAtsha204SoftPutNonce(MyMessage &msg) -{ - if (!_signing_init_ok) { - return; - } - (void)memcpy((void *)_signing_nonce, (const void *)msg.getCustom(), MIN((uint8_t)MAX_PAYLOAD_SIZE, - (uint8_t)32)); - if (MAX_PAYLOAD_SIZE < 32) { - // We set the part of the 32-byte nonce that does not fit into a message to 0xAA - (void)memset((void *)&_signing_nonce[MAX_PAYLOAD_SIZE], 0xAA, 32u - MAX_PAYLOAD_SIZE); - } -} - -bool signerAtsha204SoftSignMsg(MyMessage &msg) -{ - // If we cannot fit any signature in the message, refuse to sign it - if (msg.getLength() > MAX_PAYLOAD_SIZE - 2u) { - SIGN_DEBUG(PSTR("!SGN:BND:SIG,SIZE,%" PRIu8 ">%" PRIu8 "\n"), msg.getLength(), - MAX_PAYLOAD_SIZE - 2); //Message too large - return false; - } - - // Calculate signature of message - msg.setSigned(true); // make sure signing flag is set before signature is calculated - signerCalculateSignature(msg, true); -#if defined(MY_SIGNING_NODE_WHITELISTING) - if (DO_WHITELIST(msg.getDestination())) { - // Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has - // provided. We can reuse the nonce buffer now since it is no longer needed - (void)memcpy((void *)_signing_nonce, (const void *)_signing_hmac, 32); - _signing_nonce[32] = msg.getSender(); - (void)memcpy((void *)&_signing_nonce[33], (const void *)_signing_node_serial_info, 9); - SHA256(_signing_hmac, _signing_nonce, 32+1+9); - SIGN_DEBUG(PSTR("SGN:BND:SIG WHI,ID=%" PRIu8 "\n"), msg.getSender()); -#ifdef MY_DEBUG_VERBOSE_SIGNING - hwDebugBuf2Str(_signing_node_serial_info, 9); - SIGN_DEBUG(PSTR("SGN:BND:SIG WHI,SERIAL=%s\n"), hwDebugPrintStr); -#endif - } -#endif - - // Overwrite the first byte in the signature with the signing identifier - _signing_hmac[0] = SIGNING_IDENTIFIER; - - // Transfer as much signature data as the remaining space in the message permits - (void)memcpy((void *)&msg.data[msg.getLength()], (const void *)_signing_hmac, - MIN((uint8_t)(MAX_PAYLOAD_SIZE - msg.getLength()), (uint8_t)32)); - - return true; -} - -bool signerAtsha204SoftVerifyMsg(MyMessage &msg) -{ - if (!_signing_verification_ongoing) { - SIGN_DEBUG(PSTR("!SGN:BND:VER ONGOING\n")); - return false; - } else { - // Make sure we have not expired - if (!signerCheckTimer()) { - return false; - } - - _signing_verification_ongoing = false; - - if (msg.data[msg.getLength()] != SIGNING_IDENTIFIER) { - SIGN_DEBUG(PSTR("!SGN:BND:VER,IDENT=%" PRIu8 "\n"), msg.data[msg.getLength()]); - return false; - } - - signerCalculateSignature(msg, false); // Get signature of message - -#ifdef MY_SIGNING_NODE_WHITELISTING - // Look up the senders nodeId in our whitelist and salt the signature with that data - size_t j; - for (j = 0; j < NUM_OF(_signing_whitelist); j++) { - if (_signing_whitelist[j].nodeId == msg.getSender()) { - // We can reuse the nonce buffer now since it is no longer needed - (void)memcpy((void *)_signing_verifying_nonce, (const void *)_signing_hmac, 32); - _signing_verifying_nonce[32] = msg.getSender(); - (void)memcpy((void *)&_signing_verifying_nonce[33], (const void *)_signing_whitelist[j].serial, 9); - SHA256(_signing_hmac, _signing_verifying_nonce, 32+1+9); - SIGN_DEBUG(PSTR("SGN:BND:VER WHI,ID=%" PRIu8 "\n"), msg.getSender()); -#ifdef MY_DEBUG_VERBOSE_SIGNING - hwDebugBuf2Str(_signing_whitelist[j].serial, 9); - SIGN_DEBUG(PSTR("SGN:BND:VER WHI,SERIAL=%s\n"), hwDebugPrintStr); -#endif - break; - } - } - if (j == NUM_OF(_signing_whitelist)) { - SIGN_DEBUG(PSTR("!SGN:BND:VER WHI,ID=%" PRIu8 " MISSING\n"), msg.getSender()); - return false; - } -#endif - - // Overwrite the first byte in the signature with the signing identifier - _signing_hmac[0] = SIGNING_IDENTIFIER; - - // Compare the calculated signature with the provided signature - if (signerMemcmp(&msg.data[msg.getLength()], _signing_hmac, - MIN((uint8_t)(MAX_PAYLOAD_SIZE - msg.getLength()), (uint8_t)32))) { - return false; - } else { - return true; - } - } -} - -// Helper to calculate signature of msg (returned in _signing_hmac) -static void signerCalculateSignature(MyMessage &msg, const bool signing) -{ - // Signature is calculated on everything expect the first byte in the header - uint8_t bytes_left = msg.getLength()+HEADER_SIZE-1; - int16_t current_pos = 1-(int16_t)HEADER_SIZE; // Start at the second byte in the header - uint8_t* nonce = signing ? _signing_nonce : _signing_verifying_nonce; - -#ifdef MY_DEBUG_VERBOSE_SIGNING - hwDebugBuf2Str(nonce, 32); - SIGN_DEBUG(PSTR("SGN:BND:NONCE=%s\n"), hwDebugPrintStr); -#endif - - uint8_t _signing_temp_message[32]; - - while (bytes_left) { - uint8_t bytes_to_include = MIN(bytes_left, (uint8_t)32); - - (void)memset((void *)_signing_temp_message, 0x00, sizeof(_signing_temp_message)); - (void)memcpy((void *)_signing_temp_message, (const void *)&msg.data[current_pos], bytes_to_include); - - signerAtsha204AHmac(_signing_hmac, nonce, _signing_temp_message); - // Purge nonce when used - (void)memset((void *)nonce, 0xAA, 32); - - bytes_left -= bytes_to_include; - current_pos += bytes_to_include; - - if (bytes_left) { - // We will do another pass, use current HMAC as nonce for the next HMAC - (void)memcpy((void *)nonce, (const void *)_signing_hmac, 32); - } - } -#ifdef MY_DEBUG_VERBOSE_SIGNING - hwDebugBuf2Str(_signing_hmac, 32); - SIGN_DEBUG(PSTR("SGN:BND:HMAC=%s\n"), hwDebugPrintStr); -#endif -} - -// Helper to calculate a ATSHA204A specific HMAC-SHA256 using provided 32 byte nonce and data -// (zero padded to 32 bytes) -// The pointer to the HMAC is returned, but the HMAC is also stored in _signing_hmac -static void signerAtsha204AHmac(uint8_t *dest, const uint8_t *nonce, const uint8_t *data) -{ - // ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data: - // 32 bytes zeroes - // 32 bytes digest, - // 1 byte OPCODE (0x11) - // 1 byte Mode (0x04) - // 2 bytes SlotID (0x0000) - // 11 bytes zeroes - // SN[8] (0xEE) - // 4 bytes zeroes - // SN[0:1] (0x0123) - // 2 bytes zeroes - - // The digest is calculated as a SHA256 digest of the following: - // 32 bytes message - // 1 byte OPCODE (0x15) - // 1 byte param1 (0x02) - // 2 bytes param2 (0x0800) - // SN[8] (0xEE) - // SN[0:1] (0x0123) - // 25 bytes zeroes - // 32 bytes nonce - -#if defined(MY_CRYPTO_SHA256_ASM) - static uint8_t _signing_buffer[96]; // static for AVR ASM SHA256 -#else - uint8_t _signing_buffer[96]; -#endif - // Calculate message digest first - (void)memset((void *)_signing_buffer, 0x00, sizeof(_signing_buffer)); - (void)memcpy((void *)_signing_buffer, (const void *)data, 32); - _signing_buffer[0 + 32] = 0x15; // OPCODE - _signing_buffer[1 + 32] = 0x02; // param1 - _signing_buffer[2 + 32] = 0x08; // param2(1) - //_signing_buffer[3 + 32] = 0x00; // param2(2) - _signing_buffer[4 + 32] = 0xEE; // SN[8] - _signing_buffer[5 + 32] = 0x01; // SN[0] - _signing_buffer[6 + 32] = 0x23; // SN[1] - // _signing_buffer[7 + 32..31 + 32] => 0x00; - (void)memcpy((void *)&_signing_buffer[64], (const void *)nonce, 32); - SHA256(_signing_hmac, _signing_buffer, 96); - - // Feed "message" to HMAC calculator - (void)memset((void *)_signing_buffer, 0x00, sizeof(_signing_buffer)); - (void)memcpy((void *)&_signing_buffer[32], (const void *)_signing_hmac, 32); - _signing_buffer[0 + 64] = 0x11; // OPCODE - _signing_buffer[1 + 64] = 0x04; // Mode - //_signing_buffer[2 + 64] = 0x00; // SlotID(1) - //_signing_buffer[3 + 64] = 0x00; // SlotID(2) - //_signing_buffer[4 + 64..14 + 64] => 0x00; // 11 bytes zeroes - _signing_buffer[15 + 64] = 0xEE; // SN[8] - //_signing_buffer[16 + 64..19 + 64] => 0x00; // 4 bytes zeroes - _signing_buffer[20 + 64] = 0x01; - _signing_buffer[21 + 64] = 0x23; - //_signing_buffer[22 + 64] = 0x00; // SN[0] - //_signing_buffer[23 + 64] = 0x00; // SN[1] - SHA256HMAC(dest, _signing_hmac_key, 32, _signing_buffer, 88); -} - -#endif //MY_SIGNING_SOFT diff --git a/lib/MySensors/core/MySplashScreen.cpp b/lib/MySensors/core/MySplashScreen.cpp deleted file mode 100644 index f4c6fff1..00000000 --- a/lib/MySensors/core/MySplashScreen.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - -#include "MySensorsCore.h" - -void displaySplashScreen(void) -{ -#if !defined(MY_DISABLED_SERIAL) && defined(MY_DEBUGDEVICE) - static const uint8_t splashScreen[] PROGMEM = { - 0x20, 0x7C, 0x5F, 0x5c, 0x2F, 0x60, 0x2C, 0x0A, // substitution matrix - 0x07, 0x02, 0x20, 0x02, 0x20, 0xB2, 0x87, 0x10, 0x03, 0x40, 0x01, 0x20, 0x00, 0x24, 0x02, 0x22, - 0x10, 0x02, 0x22, 0x02, 0x02, 0x20, 0x02, 0x22, 0x00, 0x22, 0x20, 0x02, 0x02, 0x20, 0x22, 0x27, - 0x10, 0x13, 0x41, 0x01, 0x01, 0x01, 0x03, 0x22, 0x20, 0x30, 0x40, 0x20, 0x30, 0x52, 0x03, 0x40, - 0x22, 0x14, 0x02, 0x03, 0x10, 0x52, 0x24, 0x02, 0x21, 0x71, 0x01, 0x00, 0x10, 0x10, 0x12, 0x10, - 0x12, 0x22, 0x10, 0x10, 0x02, 0x24, 0x01, 0x01, 0x03, 0x22, 0x03, 0x00, 0x20, 0x01, 0x01, 0x00, - 0x32, 0x20, 0x37, 0x12, 0x10, 0x01, 0x21, 0x32, 0x26, 0x01, 0x28, 0x40, 0x32, 0x22, 0x12, 0x10, - 0x12, 0x12, 0x22, 0x43, 0x22, 0x24, 0x12, 0x10, 0x01, 0x22, 0x24, 0x70, 0xC1, 0x22, 0x24, - 0x0F, 0x0F - }; - uint8_t pos = 16; - char display = 0; - while (pos>1])); - val = (pos % 2) ? val & 0xF : val >> 4; - pos++; - if (val<8) { - display = pgm_read_byte(&(splashScreen[val])); - } - const uint8_t rep = val > 7 ? val - 5 : 1; - for (uint8_t c = 0; c -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - -#ifndef MySplashScreen_h -#define MySplashScreen_h - -/** -* Display MySensors splash screen. -*/ -void displaySplashScreen(void); - -#endif \ No newline at end of file diff --git a/lib/MySensors/core/MyTransport.cpp b/lib/MySensors/core/MyTransport.cpp deleted file mode 100644 index 240c067e..00000000 --- a/lib/MySensors/core/MyTransport.cpp +++ /dev/null @@ -1,1173 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyTransport.h" - -// debug -#if defined(MY_DEBUG_VERBOSE_TRANSPORT) -#define TRANSPORT_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< debug -extern char _convBuf[MAX_PAYLOAD_SIZE * 2 + 1]; -#else -#define TRANSPORT_DEBUG(x,...) //!< debug NULL -#endif - - -// SM: transitions and update states -static transportState_t stInit = { stInitTransition, stInitUpdate }; -static transportState_t stParent = { stParentTransition, stParentUpdate }; -static transportState_t stID = { stIDTransition, stIDUpdate }; -static transportState_t stUplink = { stUplinkTransition, stUplinkUpdate }; -static transportState_t stReady = { stReadyTransition, stReadyUpdate }; -static transportState_t stFailure = { stFailureTransition, stFailureUpdate }; - -// transport SM variables -static transportSM_t _transportSM; - -// transport configuration -static transportConfig_t _transportConfig; - -// callback transportOk -transportCallback_t _transportReady_cb = NULL; - -// enhanced ID assignment -#if !defined(MY_GATEWAY_FEATURE) && (MY_NODE_ID == AUTO) -static uint8_t _transportToken = AUTO; -#endif - -// global variables -extern MyMessage _msg; // incoming message -extern MyMessage _msgTmp; // outgoing message - -#if defined(MY_RAM_ROUTING_TABLE_ENABLED) -static routingTable_t _transportRoutingTable; //!< routing table -static uint32_t _lastRoutingTableSave; //!< last routing table dump -#endif - -// regular sanity check, activated by default on GW and repeater nodes -#if defined(MY_TRANSPORT_SANITY_CHECK) -static uint32_t _lastSanityCheck; //!< last sanity check -#endif - -// regular network discovery, sends I_DISCOVER_REQUESTS to update routing table -// sufficient to have GW triggering requests to also update repeater nodes -#if defined(MY_GATEWAY_FEATURE) -static uint32_t _lastNetworkDiscovery; //!< last network discovery -#endif - -// stInit: initialise transport HW -void stInitTransition(void) -{ - TRANSPORT_DEBUG(PSTR("TSM:INIT\n")); - // initialise status variables - _transportSM.pingActive = false; - _transportSM.transportActive = false; - _transportSM.lastUplinkCheck = 0; - -#if defined(MY_TRANSPORT_SANITY_CHECK) - _lastSanityCheck = hwMillis(); -#endif -#if defined(MY_GATEWAY_FEATURE) - _lastNetworkDiscovery = 0; -#endif -#if defined(MY_RAM_ROUTING_TABLE_ENABLED) - _lastRoutingTableSave = hwMillis(); -#endif - - // Read node settings (ID, parent ID, GW distance) from EEPROM - hwReadConfigBlock((void *)&_transportConfig, (void *)EEPROM_NODE_ID_ADDRESS, - sizeof(transportConfig_t)); -} - -void stInitUpdate(void) -{ - // initialise radio - if (!transportHALInit()) { - TRANSPORT_DEBUG(PSTR("!TSM:INIT:TSP FAIL\n")); - setIndication(INDICATION_ERR_INIT_TRANSPORT); - transportSwitchSM(stFailure); - } else { - TRANSPORT_DEBUG(PSTR("TSM:INIT:TSP OK\n")); - _transportSM.transportActive = true; -#if defined (MY_PASSIVE_NODE) - _transportConfig.passiveMode = true; - TRANSPORT_DEBUG(PSTR("TSM:INIT:TSP PSM\n")); // transport passive mode -#else - _transportConfig.passiveMode = false; -#endif -#if defined(MY_GATEWAY_FEATURE) - // Set configuration for gateway - TRANSPORT_DEBUG(PSTR("TSM:INIT:GW MODE\n")); - _transportConfig.parentNodeId = GATEWAY_ADDRESS; - _transportConfig.distanceGW = 0u; - _transportConfig.nodeId = GATEWAY_ADDRESS; - transportHALSetAddress(GATEWAY_ADDRESS); - // GW mode: skip FPAR,ID,UPL states - transportSwitchSM(stReady); -#else - if (MY_NODE_ID != AUTO) { - TRANSPORT_DEBUG(PSTR("TSM:INIT:STATID=%" PRIu8 "\n"),(uint8_t)MY_NODE_ID); - // Set static ID - _transportConfig.nodeId = (uint8_t)MY_NODE_ID; - // Save static ID to eeprom (for bootloader) - hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (uint8_t)MY_NODE_ID); - } - // assign ID if set - if (_transportConfig.nodeId == AUTO || transportAssignNodeID(_transportConfig.nodeId)) { - // if node ID valid (>0 and <255), proceed to next state - transportSwitchSM(stParent); - } else { - // ID invalid (0 or 255) - transportSwitchSM(stFailure); - } -#endif - } -} - -// stParent: find parent -void stParentTransition(void) -{ - TRANSPORT_DEBUG(PSTR("TSM:FPAR\n")); // find parent - setIndication(INDICATION_FIND_PARENT); - _transportSM.uplinkOk = false; - _transportSM.preferredParentFound = false; -#if defined(MY_PARENT_NODE_IS_STATIC) || defined(MY_PASSIVE_NODE) - TRANSPORT_DEBUG(PSTR("TSM:FPAR:STATP=%" PRIu8 "\n"), (uint8_t)MY_PARENT_NODE_ID); // static parent - _transportSM.findingParentNode = false; - _transportConfig.distanceGW = 1u; // assumption, CHKUPL:GWDC will update this variable - _transportConfig.parentNodeId = (uint8_t)MY_PARENT_NODE_ID; - // save parent ID to eeprom (for bootloader) - hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, (uint8_t)MY_PARENT_NODE_ID); -#else - _transportSM.findingParentNode = true; - _transportConfig.distanceGW = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID - _transportConfig.parentNodeId = AUTO; - // Broadcast find parent request - (void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_FIND_PARENT_REQUEST).set("")); -#endif -} - -// stParentUpdate -void stParentUpdate(void) -{ -#if defined(MY_PARENT_NODE_IS_STATIC) || defined(MY_PASSIVE_NODE) - // skipping find parent - setIndication(INDICATION_GOT_PARENT); - transportSwitchSM(stID); -#else - if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS || _transportSM.preferredParentFound) { - // timeout or preferred parent found - if (_transportConfig.parentNodeId != AUTO) { - // parent assigned - TRANSPORT_DEBUG(PSTR("TSM:FPAR:OK\n")); // find parent ok - _transportSM.findingParentNode = false; - setIndication(INDICATION_GOT_PARENT); - // go to next state - transportSwitchSM(stID); - } else { - // timeout w/o reply or valid parent - if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { - // retries left - TRANSPORT_DEBUG(PSTR("!TSM:FPAR:NO REPLY\n")); // find parent, no reply - // reenter state - transportSwitchSM(stParent); - } else { - // no retries left, finding parent failed - TRANSPORT_DEBUG(PSTR("!TSM:FPAR:FAIL\n")); - setIndication(INDICATION_ERR_FIND_PARENT); - transportSwitchSM(stFailure); - } - } - } -#endif -} - -// stID: verify and request ID if necessary -void stIDTransition(void) -{ - TRANSPORT_DEBUG(PSTR("TSM:ID\n")); // verify/request node ID - if (_transportConfig.nodeId == AUTO) { - // send ID request - setIndication(INDICATION_REQ_NODEID); -#if !defined(MY_GATEWAY_FEATURE) && (MY_NODE_ID == AUTO) - _transportToken = (uint8_t)(hwMillis() & 0xFF); - if (_transportToken == AUTO) { - _transportToken++; // AUTO as token not allowed - } - const uint8_t sensorID = _transportToken; -#else - const uint8_t sensorID = NODE_SENSOR_ID; -#endif - TRANSPORT_DEBUG(PSTR("TSM:ID:REQ\n")); // request node ID - (void)transportRouteMessage(build(_msgTmp, GATEWAY_ADDRESS, sensorID, C_INTERNAL, - I_ID_REQUEST).set("")); - } -} - -void stIDUpdate(void) -{ - if (_transportConfig.nodeId != AUTO) { - // current node ID is valid - TRANSPORT_DEBUG(PSTR("TSM:ID:OK\n")); - setIndication(INDICATION_GOT_NODEID); - // proceed to next state - transportSwitchSM(stUplink); - } else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) { - // timeout - if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { - // retries left: reenter state - transportSwitchSM(stID); - } else { - // no retries left - TRANSPORT_DEBUG(PSTR("!TSM:ID:FAIL\n")); - setIndication(INDICATION_ERR_GET_NODEID); - transportSwitchSM(stFailure); - } - } -} - -void stUplinkTransition(void) -{ -#if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED) - TRANSPORT_DEBUG(PSTR("TSM:UPL\n")); - setIndication(INDICATION_CHECK_UPLINK); - _transportSM.pingResponse = INVALID_HOPS; - _transportSM.pingActive = true; - (void)transportRouteMessage(build(_msgTmp,GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_PING).set((uint8_t)0x01)); -#endif -} - -void stUplinkUpdate(void) -{ -#if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED) - if (_transportSM.pingResponse != INVALID_HOPS) { - _transportSM.lastUplinkCheck = hwMillis(); - // uplink ok, i.e. GW replied - TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok - if (_transportSM.pingResponse != _transportConfig.distanceGW) { - TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%" PRIu8 ",N=%" PRIu8 "\n"), _transportConfig.distanceGW, - _transportSM.pingResponse); // distance to GW changed - _transportConfig.distanceGW = _transportSM.pingResponse; - } - transportSwitchSM(stReady); // proceed to next state - } else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) { - // timeout - if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { - // retries left: reenter state - transportSwitchSM(stUplink); - } else { - // no retries left - TRANSPORT_DEBUG(PSTR("!TSM:UPL:FAIL\n")); // uplink check failed - _transportSM.pingActive = false; - setIndication(INDICATION_ERR_CHECK_UPLINK); - transportSwitchSM(stParent); // go back to stParent - } - } -#else - TRANSPORT_DEBUG(PSTR("TSM:UPL:DISABLED\n")); // uplink check disabled - transportSwitchSM(stReady); -#endif -} - -void stReadyTransition(void) -{ - // transport is ready and fully operational - TRANSPORT_DEBUG(PSTR("TSM:READY:ID=%" PRIu8 ",PAR=%" PRIu8 ",DIS=%" PRIu8 "\n"), - _transportConfig.nodeId, - _transportConfig.parentNodeId, _transportConfig.distanceGW); - _transportSM.uplinkOk = true; - _transportSM.failureCounter = 0u; // reset failure counter - _transportSM.failedUplinkTransmissions = 0u; // reset failed uplink TX counter - // callback - if (_transportReady_cb) { - _transportReady_cb(); - } -} - -// stReadyUpdate: monitors link -void stReadyUpdate(void) -{ -#if defined(MY_GATEWAY_FEATURE) - if (!_lastNetworkDiscovery || - (hwMillis() - _lastNetworkDiscovery > MY_TRANSPORT_DISCOVERY_INTERVAL_MS)) { - _lastNetworkDiscovery = hwMillis(); - TRANSPORT_DEBUG(PSTR("TSM:READY:NWD REQ\n")); // send transport network discovery - (void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_DISCOVER_REQUEST).set("")); - } -#else - if (_transportSM.failedUplinkTransmissions > MY_TRANSPORT_MAX_TX_FAILURES) { - // too many uplink transmissions failed, find new parent (if non-static) -#if !defined(MY_PARENT_NODE_IS_STATIC) - TRANSPORT_DEBUG(PSTR("!TSM:READY:UPL FAIL,SNP\n")); // uplink failed, search new parent - transportSwitchSM(stParent); -#else - TRANSPORT_DEBUG(PSTR("!TSM:READY:UPL FAIL,STATP\n")); // uplink failed, static parent - // reset counter - _transportSM.failedUplinkTransmissions = 0u; -#endif - } -#endif - -#if defined(MY_RAM_ROUTING_TABLE_ENABLED) - if (hwMillis() - _lastRoutingTableSave > MY_ROUTING_TABLE_SAVE_INTERVAL_MS) { - _lastRoutingTableSave = hwMillis(); - transportSaveRoutingTable(); - } -#endif -} - -// stFailure: entered upon HW init failure or max retries exceeded -void stFailureTransition(void) -{ - if (_transportSM.failureCounter < MY_TRANSPORT_MAX_TSM_FAILURES) { - _transportSM.failureCounter++; // increment consecutive TSM failure counter - } - TRANSPORT_DEBUG(PSTR("TSM:FAIL:CNT=%" PRIu8 "\n"),_transportSM.failureCounter); - _transportSM.uplinkOk = false; // uplink nok - _transportSM.transportActive = false; // transport inactive - setIndication(INDICATION_ERR_INIT_TRANSPORT); -#if defined(MY_SENSOR_NETWORK) - TRANSPORT_DEBUG(PSTR("TSM:FAIL:DIS\n")); // disable transport, no need until re-init - transportDisable(); // sleep -#endif -} - -void stFailureUpdate(void) -{ - if (transportTimeInState() > ( isTransportExtendedFailure()? - MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE_MS: - MY_TRANSPORT_TIMEOUT_FAILURE_STATE_MS) ) { - TRANSPORT_DEBUG(PSTR("TSM:FAIL:RE-INIT\n")); // attempt to re-initialise transport - transportSwitchSM(stInit); - } -} - -void transportSwitchSM(transportState_t &newState) -{ - if (_transportSM.currentState != &newState) { - _transportSM.stateRetries = 0u; // state change, reset retry counter - _transportSM.currentState = &newState; // change state - } else { - _transportSM.stateRetries++; // increment retries - } - if (_transportSM.currentState) { - _transportSM.currentState->Transition(); // State transition - } - _transportSM.stateEnter = hwMillis(); // save time -} - -uint32_t transportTimeInState(void) -{ - return hwMillis() - _transportSM.stateEnter; -} - -void transportUpdateSM(void) -{ - if (_transportSM.currentState) { - _transportSM.currentState->Update(); - } -} - -bool isTransportReady(void) -{ - return _transportSM.uplinkOk; -} - -bool isTransportExtendedFailure(void) -{ - return _transportSM.failureCounter == MY_TRANSPORT_MAX_TSM_FAILURES; -} - -bool isTransportSearchingParent(void) -{ - return _transportSM.findingParentNode; -} - -bool isMessageReceived(void) -{ - return _transportSM.msgReceived; -} - -void resetMessageReceived(void) -{ - _transportSM.msgReceived = false; -} - -void transportInitialise(void) -{ - _transportSM.failureCounter = 0u; // reset failure counter - transportLoadRoutingTable(); // load routing table to RAM (if feature enabled) - // initial state - _transportSM.currentState = NULL; - transportSwitchSM(stInit); -} - -void transportDisable(void) -{ - if (RADIO_CAN_POWER_OFF == true) { - TRANSPORT_DEBUG(PSTR("TSF:TDI:TPD\n")); // power down transport - transportHALPowerDown(); - } else { - TRANSPORT_DEBUG(PSTR("TSF:TDI:TSL\n")); // send transport to sleep - transportHALSleep(); - } -} - -void transportReInitialise(void) -{ - if (RADIO_CAN_POWER_OFF == true) { - TRANSPORT_DEBUG(PSTR("TSF:TRI:TPU\n")); // transport power up - transportHALPowerUp(); - transportHALSetAddress(_transportConfig.nodeId); - } else { - TRANSPORT_DEBUG(PSTR("TSF:TRI:TSB\n")); // transport standby - transportHALStandBy(); - } -} - -bool transportWaitUntilReady(const uint32_t waitingMS) -{ - // check if transport ready - TRANSPORT_DEBUG(PSTR("TSF:WUR:MS=%" PRIu32 "\n"), waitingMS); // timeout - uint32_t enterMS = hwMillis(); - bool result = false; - while (!result && ( hwMillis() - enterMS < waitingMS || !waitingMS)) { - transportProcess(); - result = isTransportReady(); - doYield(); - } - return result; -} - -// update TSM and process incoming messages -void transportProcess(void) -{ - // update state machine - transportUpdateSM(); - // process transport FIFO - transportProcessFIFO(); -} - -bool transportCheckUplink(const bool force) -{ - if (!force && (hwMillis() - _transportSM.lastUplinkCheck) < MY_TRANSPORT_CHKUPL_INTERVAL_MS) { - TRANSPORT_DEBUG(PSTR("TSF:CKU:OK,FCTRL\n")); // flood control - return true; - } - // ping GW - const uint8_t hopsCount = transportPingNode(GATEWAY_ADDRESS); - // verify hops - if (hopsCount != INVALID_HOPS) { - // update - _transportSM.lastUplinkCheck = hwMillis(); - TRANSPORT_DEBUG(PSTR("TSF:CKU:OK\n")); - // did distance to GW change upstream, eg. re-routing of uplink nodes - if (hopsCount != _transportConfig.distanceGW) { - TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%" PRIu8 ",N=%" PRIu8 "\n"), _transportConfig.distanceGW, - hopsCount); // distance to GW changed - _transportConfig.distanceGW = hopsCount; - } - return true; - } else { - TRANSPORT_DEBUG(PSTR("TSF:CKU:FAIL\n")); - return false; - } -} - -bool transportAssignNodeID(const uint8_t newNodeId) -{ - // verify if ID valid - if (newNodeId != GATEWAY_ADDRESS && newNodeId != AUTO) { - _transportConfig.nodeId = newNodeId; - transportHALSetAddress(newNodeId); - // Write ID to EEPROM - hwWriteConfig(EEPROM_NODE_ID_ADDRESS, newNodeId); - TRANSPORT_DEBUG(PSTR("TSF:SID:OK,ID=%" PRIu8 "\n"),newNodeId); // Node ID assigned - return true; - } else { - TRANSPORT_DEBUG(PSTR("!TSF:SID:FAIL,ID=%" PRIu8 "\n"),newNodeId); // ID is invalid, cannot assign ID - setIndication(INDICATION_ERR_NET_FULL); - return false; - } -} - -bool transportRouteMessage(MyMessage &message) -{ - const uint8_t destination = message.getDestination(); - - if (_transportSM.findingParentNode && destination != BROADCAST_ADDRESS) { - TRANSPORT_DEBUG(PSTR("!TSF:RTE:FPAR ACTIVE\n")); // find parent active, message not sent - // request to send a non-BC message while finding parent active, abort - return false; - } - - uint8_t route; - - if (destination == GATEWAY_ADDRESS) { - route = _transportConfig.parentNodeId; // message to GW always routes via parent - } else if (destination == BROADCAST_ADDRESS) { - route = BROADCAST_ADDRESS; // message to BC does not require routing - } else { -#if defined(MY_REPEATER_FEATURE) - // destination not GW & not BC, get route - route = transportGetRoute(destination); - if (route == AUTO) { - TRANSPORT_DEBUG(PSTR("!TSF:RTE:%" PRIu8 " UNKNOWN\n"), destination); // route unknown -#if !defined(MY_GATEWAY_FEATURE) - if (message.getLast() != _transportConfig.parentNodeId) { - // message not from parent, i.e. child node - route it to parent - route = _transportConfig.parentNodeId; - } else { - // route unknown and msg received from parent, send it to destination assuming in rx radius - route = destination; - } -#else - // if GW, all unknown destinations are directly addressed - route = destination; -#endif - } -#else - if (destination > GATEWAY_ADDRESS && destination < BROADCAST_ADDRESS) { - // node2node traffic: assume node is in vincinity. If transmission fails, hand over to parent - if (transportSendWrite(destination, message)) { - TRANSPORT_DEBUG(PSTR("TSF:RTE:N2N OK\n")); - return true; - } - TRANSPORT_DEBUG(PSTR("!TSF:RTE:N2N FAIL\n")); - } - route = _transportConfig.parentNodeId; // not a repeater, all traffic routed via parent -#endif - } - // send message - const bool result = transportSendWrite(route, message); -#if !defined(MY_GATEWAY_FEATURE) - // update counter - if (route == _transportConfig.parentNodeId) { - - if (!result) { - setIndication(INDICATION_ERR_TX); - _transportSM.failedUplinkTransmissions++; - } else { - _transportSM.failedUplinkTransmissions = 0u; -#if defined(MY_SIGNAL_REPORT_ENABLED) - // update uplink quality monitor - const int16_t signalStrengthRSSI = transportGetSignalReport(SR_TX_RSSI); - _transportSM.uplinkQualityRSSI = static_cast((1 - UPLINK_QUALITY_WEIGHT) * - _transportSM.uplinkQualityRSSI - + (UPLINK_QUALITY_WEIGHT * transportRSSItoInternal(signalStrengthRSSI))); -#endif - } - } -#else - if(!result) { - setIndication(INDICATION_ERR_TX); - } -#endif - - return result; -} - -bool transportSendRoute(MyMessage &message) -{ - bool result = false; - if (isTransportReady()) { - result = transportRouteMessage(message); - } else { - // TNR: transport not ready - TRANSPORT_DEBUG(PSTR("!TSF:SND:TNR\n")); - } - return result; -} - -// only be used inside transport -bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) -{ - const uint32_t enterMS = hwMillis(); - // invalidate msg type - _msg.setType(!msgType); - bool expectedResponse = false; - while ((hwMillis() - enterMS < waitingMS) && !expectedResponse) { - // process incoming messages - transportProcessFIFO(); - doYield(); - expectedResponse = (_msg.getCommand() == cmd && _msg.getType() == msgType); - } - return expectedResponse; -} - -uint8_t transportPingNode(const uint8_t targetId) -{ - if(!_transportSM.pingActive) { - TRANSPORT_DEBUG(PSTR("TSF:PNG:SEND,TO=%" PRIu8 "\n"), targetId); - if(targetId == _transportConfig.nodeId) { - // pinging self - _transportSM.pingResponse = 0u; - } else { - _transportSM.pingActive = true; - _transportSM.pingResponse = INVALID_HOPS; - (void)transportRouteMessage(build(_msgTmp, targetId, NODE_SENSOR_ID, C_INTERNAL, - I_PING).set((uint8_t)0x01)); - // Wait for ping reply or timeout - (void)transportWait(2000, C_INTERNAL, I_PONG); - } - // make sure missing I_PONG msg does not block pinging function by leaving pingActive=true - _transportSM.pingActive = false; - return _transportSM.pingResponse; - } else { - TRANSPORT_DEBUG(PSTR("!TSF:PNG:ACTIVE\n")); // ping active, cannot start new ping - return INVALID_HOPS; - } -} - -uint32_t transportGetHeartbeat(void) -{ - return transportTimeInState(); -} - -void transportProcessMessage(void) -{ - // Manage signing timeout - (void)signerCheckTimer(); - // receive message - setIndication(INDICATION_RX); - uint8_t payloadLength; - // last is the first byte of the payload buffer - if (!transportHALReceive(&_msg, &payloadLength)) { - return; - } - // get message length and limit size - const uint8_t msgLength = _msg.getLength(); - // calculate expected length - - const uint8_t command = _msg.getCommand(); - const uint8_t type = _msg.getType(); - const uint8_t sender = _msg.getSender(); - const uint8_t last = _msg.getLast(); - const uint8_t destination = _msg.getDestination(); - - TRANSPORT_DEBUG(PSTR("TSF:MSG:READ,%" PRIu8 "-%" PRIu8 "-%" PRIu8 ",s=%" PRIu8 ",c=%" PRIu8 ",t=%" - PRIu8 ",pt=%" PRIu8 ",l=%" PRIu8 ",sg=%" PRIu8 ":%s\n"), - sender, last, destination, _msg.getSensor(), command, type, _msg.getPayloadType(), msgLength, - _msg.getSigned(), ((command == C_INTERNAL && - type == I_NONCE_RESPONSE) ? "" : _msg.getString(_convBuf))); - - // Reject messages that do not pass verification - if (!signerVerifyMsg(_msg)) { - setIndication(INDICATION_ERR_SIGN); - TRANSPORT_DEBUG(PSTR("!TSF:MSG:SIGN VERIFY FAIL\n")); - return; - } - - // update routing table if msg not from parent -#if defined(MY_REPEATER_FEATURE) -#if !defined(MY_GATEWAY_FEATURE) - if (last != _transportConfig.parentNodeId) { -#else - // GW doesn't have parent - { -#endif - // Message is from one of the child nodes and not sent from this node. Add it to routing table. - if (sender != _transportConfig.nodeId) - { - transportSetRoute(sender, last); - } - } -#endif // MY_REPEATER_FEATURE - - // set message received flag - _transportSM.msgReceived = true; - - // Is message addressed to this node? - if (destination == _transportConfig.nodeId) { - // null terminate data - _msg.data[msgLength] = 0u; - // Check if sender requests an echo. - if (_msg.getRequestEcho()) { - TRANSPORT_DEBUG(PSTR("TSF:MSG:ECHO REQ\n")); // ECHO requested - _msgTmp = _msg; // Copy message - // Reply without echo flag (otherwise we would end up in an eternal loop) - _msgTmp.setRequestEcho(false); - _msgTmp.setEcho(true); // set ECHO flag - _msgTmp.setSender(_transportConfig.nodeId); - _msgTmp.setDestination(sender); - // send ECHO, use transportSendRoute since ECHO reply is not internal, i.e. if !transportOK do not reply - (void)transportSendRoute(_msgTmp); - } - if(!_msg.isEcho()) { - // only process if not ECHO - if (command == C_INTERNAL) { - // Process signing related internal messages - if (signerProcessInternal(_msg)) { - return; // Signer processing indicated no further action needed - } -#if !defined(MY_GATEWAY_FEATURE) - if (type == I_ID_RESPONSE) { -#if (MY_NODE_ID == AUTO) - // only active if node ID dynamic - if ((_msg.getSensor() == _transportToken) || (_msg.getSensor() == AUTO)) { - (void)transportAssignNodeID(_msg.getByte()); - } else { - TRANSPORT_DEBUG(PSTR("!TSF:MSG:ID TK INVALID\n")); - } -#endif - return; // no further processing required - } - if (type == I_FIND_PARENT_RESPONSE) { -#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_PARENT_NODE_IS_STATIC) - if (_transportSM.findingParentNode) { // only process if find parent active - // Reply to a I_FIND_PARENT_REQUEST message. Check if the distance is shorter than we already have. - uint8_t distance = _msg.getByte(); - if (isValidDistance(distance)) { - distance++; // Distance to gateway is one more for us w.r.t. parent - // update settings if distance shorter or preferred parent found - if (((isValidDistance(distance) && distance < _transportConfig.distanceGW) || (!_autoFindParent && - sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) { - // Found a neighbor closer to GW than previously found - if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) { - _transportSM.preferredParentFound = true; - TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR PREF\n")); // find parent, preferred parent found - } - _transportConfig.distanceGW = distance; - _transportConfig.parentNodeId = sender; - TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%" PRIu8 ",D=%" PRIu8 "\n"), _transportConfig.parentNodeId, - _transportConfig.distanceGW); - } - } - } else { - TRANSPORT_DEBUG(PSTR("!TSF:MSG:FPAR INACTIVE\n")); // find parent response received, but inactive - } - return; // no further processing required -#endif - } -#endif // !defined(MY_GATEWAY_FEATURE) - // general - if (type == I_PING) { - TRANSPORT_DEBUG(PSTR("TSF:MSG:PINGED,ID=%" PRIu8 ",HP=%" PRIu8 "\n"), sender, - _msg.getByte()); // node pinged -#if defined(MY_GATEWAY_FEATURE) && (F_CPU>16000000) - // delay for fast GW and slow nodes - delay(5); -#endif - (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, - I_PONG).set((uint8_t)1)); - return; // no further processing required - } - if (type == I_PONG) { - if (_transportSM.pingActive) { - _transportSM.pingActive = false; - _transportSM.pingResponse = _msg.getByte(); - TRANSPORT_DEBUG(PSTR("TSF:MSG:PONG RECV,HP=%" PRIu8 "\n"), - _transportSM.pingResponse); // pong received - } else { - TRANSPORT_DEBUG(PSTR("!TSF:MSG:PONG RECV,INACTIVE\n")); // pong received, but !pingActive - } - return; // no further processing required - } - if (type == I_SIGNAL_REPORT_REVERSE) { - return; // no further processing required - } - if (type == I_SIGNAL_REPORT_REQUEST) { - int16_t value = INVALID_RSSI; -#if defined(MY_SIGNAL_REPORT_ENABLED) - const char internalCommand = _msg.data[0]; - if (_msg.data[1] != '!') { - value = transportSignalReport(internalCommand); - } else { - // send request - if (transportRouteMessage(build(_msgTmp, _msg.getLast(), NODE_SENSOR_ID, C_INTERNAL, - I_SIGNAL_REPORT_REVERSE).set((uint8_t)255))) { - // S>s, R>r, ascii delta = 32 - value = transportSignalReport(internalCommand + 32); // reverse - }; - } -#endif - (void)transportRouteMessage(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, - I_SIGNAL_REPORT_RESPONSE).set(value)); - return; // no further processing required - } - if (_processInternalCoreMessage()) { - return; // no further processing required - } - } else if (command == C_STREAM) { -#if defined(MY_OTA_FIRMWARE_FEATURE) - if(firmwareOTAUpdateProcess()) { - return; // OTA FW update processing indicated no further action needed - } -#endif - } - } else { - TRANSPORT_DEBUG( - PSTR("TSF:MSG:ECHO\n")); // received message is ECHO, no internal processing, handover to msg callback - } -#if defined(MY_OTA_LOG_RECEIVER_FEATURE) - if ((type == I_LOG_MESSAGE) && (command == C_INTERNAL)) { - OTALogPrint(_msg); - return; // no further processing required - } -#endif //defined(MY_OTA_LOG_RECEIVER_FEATURE) -#if defined(MY_GATEWAY_FEATURE) - // Hand over message to controller - (void)gatewayTransportSend(_msg); -#endif - // Call incoming message callback if available - if (receive) { - receive(_msg); - } - } else if (destination == BROADCAST_ADDRESS) { - TRANSPORT_DEBUG(PSTR("TSF:MSG:BC\n")); // broadcast msg - if (command == C_INTERNAL) { - if (isTransportReady()) { - // only reply if node is fully operational - if (type == I_FIND_PARENT_REQUEST) { -#if defined(MY_REPEATER_FEATURE) - if (sender != _transportConfig.parentNodeId) { // no circular reference - TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR REQ,ID=%" PRIu8 "\n"), sender); // FPAR: find parent request - // check if uplink functional - node can only be parent node if link to GW functional - // this also prevents circular references in case GW ooo - if (transportCheckUplink()) { - _transportSM.lastUplinkCheck = hwMillis(); - TRANSPORT_DEBUG(PSTR("TSF:MSG:GWL OK\n")); // GW uplink ok - // random delay minimizes collisions - delay(hwMillis() & 0x3ff); - (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, - I_FIND_PARENT_RESPONSE).set(_transportConfig.distanceGW)); - } else { - TRANSPORT_DEBUG(PSTR("!TSF:MSG:GWL FAIL\n")); // GW uplink fail, do not respond to parent request - } - } -#endif - return; // no further processing required, do not forward - } - } // isTransportReady - if (type == I_FIND_PARENT_RESPONSE) { - return; // no further processing required, do not forward - } -#if !defined(MY_GATEWAY_FEATURE) - if (type == I_DISCOVER_REQUEST) { - if (last == _transportConfig.parentNodeId) { - // random wait to minimize collisions - delay(hwMillis() & 0x3ff); - (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, - I_DISCOVER_RESPONSE).set(_transportConfig.parentNodeId)); - // no return here (for fwd if repeater) - } - } -#endif - } - // controlled BC relay -#if defined(MY_REPEATER_FEATURE) - // controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds - if(last == _transportConfig.parentNodeId && sender != _transportConfig.nodeId && - isTransportReady()) { - TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding - (void)transportRouteMessage(_msg); - } -#endif - - // Callback for BC, only for non-internal messages - if (command != C_INTERNAL) { -#if !defined(MY_GATEWAY_FEATURE) - // only proceed if message received from parent - if (last != _transportConfig.parentNodeId) { - return; - } -#endif -#if defined(MY_GATEWAY_FEATURE) - // Hand over message to controller - (void)gatewayTransportSend(_msg); -#endif - if (receive) { - TRANSPORT_DEBUG(PSTR("TSF:MSG:RCV CB\n")); // hand over message to receive callback function - receive(_msg); - } - } - - } else { - // msg not to us and not BC, relay msg -#if defined(MY_REPEATER_FEATURE) - if (isTransportReady()) { - if (command == C_INTERNAL) { - if (type == I_PING || type == I_PONG) { - uint8_t hopsCnt = _msg.getByte(); - TRANSPORT_DEBUG(PSTR("TSF:MSG:REL PxNG,HP=%" PRIu8 "\n"), hopsCnt); - if (hopsCnt != MAX_HOPS) { - hopsCnt++; - _msg.set(hopsCnt); - } - } - } - // Relay this message to another node - TRANSPORT_DEBUG(PSTR("TSF:MSG:REL MSG\n")); // relay msg - (void)transportRouteMessage(_msg); - } -#else - TRANSPORT_DEBUG(PSTR("!TSF:MSG:REL MSG,NREP\n")); // message relaying request, but not a repeater -#endif - } - (void)last; //avoid cppcheck warning -} - -void transportInvokeSanityCheck(void) -{ - // Suppress this because the function may return a variable value in some configurations - // cppcheck-suppress knownConditionTrueFalse - if (!transportHALSanityCheck()) { - TRANSPORT_DEBUG(PSTR("!TSF:SAN:FAIL\n")); // sanity check fail - transportSwitchSM(stFailure); - } else { - TRANSPORT_DEBUG(PSTR("TSF:SAN:OK\n")); // sanity check ok - } -} - -void transportProcessFIFO(void) -{ - if (!_transportSM.transportActive) { - // transport not active, no further processing required - return; - } - -#if defined(MY_TRANSPORT_SANITY_CHECK) - if (hwMillis() - _lastSanityCheck > MY_TRANSPORT_SANITY_CHECK_INTERVAL_MS) { - _lastSanityCheck = hwMillis(); - transportInvokeSanityCheck(); - } -#endif - - uint8_t _processedMessages = MAX_SUBSEQ_MSGS; - // process all msgs in FIFO or counter exit - while (transportHALDataAvailable() && _processedMessages--) { - transportProcessMessage(); - } -#if defined(MY_OTA_FIRMWARE_FEATURE) - if (isTransportReady()) { - // only process if transport ok - firmwareOTAUpdateRequest(); - } -#endif -} - -bool transportSendWrite(const uint8_t to, MyMessage &message) -{ - message.setLast(_transportConfig.nodeId); // Update last - - // sign message if required - if (!signerSignMsg(message)) { - TRANSPORT_DEBUG(PSTR("!TSF:MSG:SIGN FAIL\n")); - setIndication(INDICATION_ERR_SIGN); - return false; - } - - // msg length changes if signed - const uint8_t totalMsgLength = HEADER_SIZE + ( message.getSigned() ? MAX_PAYLOAD_SIZE : - message.getLength() ); - const bool noACK = _transportConfig.passiveMode || (to == BROADCAST_ADDRESS); - // send - setIndication(INDICATION_TX); - const bool result = transportHALSend(to, &message, totalMsgLength, - noACK); - - TRANSPORT_DEBUG(PSTR("%sTSF:MSG:SEND,%" PRIu8 "-%" PRIu8 "-%" PRIu8 "-%" PRIu8 ",s=%" PRIu8 ",c=%" - PRIu8 ",t=%" PRIu8 ",pt=%" PRIu8 ",l=%" PRIu8 ",sg=%" PRIu8 ",ft=%" PRIu8 ",st=%s:%s\n"), - (noACK ? "?" : result ? "" : "!"), message.getSender(), message.getLast(), - to, - message.getDestination(), - message.getSensor(), - message.getCommand(), message.getType(), - message.getPayloadType(), message.getLength(), message.getSigned(), - _transportSM.failedUplinkTransmissions, - (result ? "OK" : "NACK"), - ((message.getCommand() == C_INTERNAL && - message.getType() == I_NONCE_RESPONSE) ? "" : message.getString(_convBuf))); - - return result; -} - -void transportRegisterReadyCallback(transportCallback_t cb) -{ - _transportReady_cb = cb; -} - -uint8_t transportGetNodeId(void) -{ - return _transportConfig.nodeId; -} -uint8_t transportGetParentNodeId(void) -{ - return _transportConfig.parentNodeId; -} -uint8_t transportGetDistanceGW(void) -{ - return _transportConfig.distanceGW; -} - - -void transportClearRoutingTable(void) -{ - for (uint16_t i = 0; i < SIZE_ROUTES; i++) { - transportSetRoute((uint8_t)i, BROADCAST_ADDRESS); - } - transportSaveRoutingTable(); // save cleared routing table to EEPROM (if feature enabled) - TRANSPORT_DEBUG(PSTR("TSF:CRT:OK\n")); // clear routing table -} - -void transportLoadRoutingTable(void) -{ -#if defined(MY_RAM_ROUTING_TABLE_ENABLED) - hwReadConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES); - TRANSPORT_DEBUG(PSTR("TSF:LRT:OK\n")); // load routing table -#endif -} - -void transportSaveRoutingTable(void) -{ -#if defined(MY_RAM_ROUTING_TABLE_ENABLED) - hwWriteConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES); - TRANSPORT_DEBUG(PSTR("TSF:SRT:OK\n")); // save routing table -#endif -} - -void transportSetRoute(const uint8_t node, const uint8_t route) -{ -#if defined(MY_RAM_ROUTING_TABLE_ENABLED) - _transportRoutingTable.route[node] = route; -#else - hwWriteConfig(EEPROM_ROUTES_ADDRESS + node, route); -#endif -} - -uint8_t transportGetRoute(const uint8_t node) -{ - uint8_t result; -#if defined(MY_RAM_ROUTING_TABLE_ENABLED) - result = _transportRoutingTable.route[node]; -#else - result = hwReadConfig(EEPROM_ROUTES_ADDRESS + node); -#endif - return result; -} - -void transportReportRoutingTable(void) -{ -#if defined(MY_REPEATER_FEATURE) - for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) { - const uint8_t route = transportGetRoute(cnt); - if (route != BROADCAST_ADDRESS) { - TRANSPORT_DEBUG(PSTR("TSF:RRT:ROUTE N=%" PRIu8 ",R=%" PRIu8 "\n"), cnt, route); - uint8_t outBuf[2] = { (uint8_t)cnt,route }; - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, - 2)); - wait(200); - } - } -#endif -} - -void transportTogglePassiveMode(const bool OnOff) -{ -#if !defined (MY_PASSIVE_NODE) - _transportConfig.passiveMode = OnOff; -#else - (void)OnOff; -#endif -} - -int16_t transportGetSignalReport(const signalReport_t signalReport) -{ -#if defined(MY_SIGNAL_REPORT_ENABLED) - int16_t result; - switch (signalReport) { - case SR_RX_RSSI: - result = transportHALGetReceivingRSSI(); - break; - case SR_TX_RSSI: - result = transportHALGetSendingRSSI(); - break; - case SR_RX_SNR: - result = transportHALGetReceivingSNR(); - break; - case SR_TX_SNR: - result = transportHALGetSendingSNR(); - break; - case SR_TX_POWER_LEVEL: - result = transportHALGetTxPowerLevel(); - break; - case SR_TX_POWER_PERCENT: - result = transportHALGetTxPowerPercent(); - break; - case SR_UPLINK_QUALITY: - result = transportInternalToRSSI(_transportSM.uplinkQualityRSSI); - break; - default: - result = 0; - break; - } - return result; -#else - (void)signalReport; - return 0; -#endif -} - -int16_t transportSignalReport(const char command) -{ -#if defined(MY_SIGNAL_REPORT_ENABLED) - signalReport_t reportCommand; - switch (command) { - case 'S': - // SNR (if available) of incoming message - reportCommand = SR_RX_SNR; - break; - case 's': - // SNR (if available) of incoming ACK message - reportCommand = SR_TX_SNR; - break; - case 'R': - // RSSI (if available) of incoming message - reportCommand = SR_RX_RSSI; - break; - case 'r': - // RSSI (if available) of incoming ACK message - reportCommand = SR_TX_RSSI; - break; - case 'P': - // TX powerlevel in % - reportCommand = SR_TX_POWER_PERCENT; - break; - case 'T': - // TX powerlevel in dBm - reportCommand = SR_TX_POWER_LEVEL; - break; - case 'U': - // Uplink quality - reportCommand = SR_UPLINK_QUALITY; - break; - default: - reportCommand = SR_NOT_DEFINED; - break; - } - const uint16_t result = transportGetSignalReport(reportCommand); - TRANSPORT_DEBUG(PSTR("TSF:SIR:CMD=%" PRIu8 ",VAL=%" PRIu16 "\n"), reportCommand, result); - return result; -#else - (void)command; - return 0; -#endif -} diff --git a/lib/MySensors/core/MyTransport.h b/lib/MySensors/core/MyTransport.h deleted file mode 100644 index 329fc722..00000000 --- a/lib/MySensors/core/MyTransport.h +++ /dev/null @@ -1,573 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** -* @file MyTransport.h -* -* @defgroup MyTransportgrp MyTransport -* @ingroup internals -* @{ -* -* Transport-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE -* - [!] Exclamation mark is prepended in case of error -* - SYSTEM: -* - TSM: messages emitted by the transport state machine -* - TSF: messages emitted by transport support functions -* - SUB SYSTEMS: -* - Transport state machine (TSM) -* - TSM:INIT from stInit Initialize transport and radio -* - TSM:FPAR from stParent Find parent -* - TSM:ID from stID Check/request node ID, if dynamic node ID set -* - TSM:UPL from stUplink Verify uplink connection by pinging GW -* - TSM:READY from stReady Transport is ready and fully operational -* - TSM:FAIL from stFailure Failure in transport link or transport HW -* - Transport support function (TSF) -* - TSF:CKU from @ref transportCheckUplink(), checks connection to GW -* - TSF:SID from @ref transportAssignNodeID(), assigns node ID -* - TSF:PNG from @ref transportPingNode(), pings a node -* - TSF:WUR from @ref transportWaitUntilReady(), waits until transport is ready -* - TSF:CRT from @ref transportClearRoutingTable(), clears routing table stored in EEPROM -* - TSF:LRT from @ref transportLoadRoutingTable(), loads RAM routing table from EEPROM (only GW/repeaters) -* - TSF:SRT from @ref transportSaveRoutingTable(), saves RAM routing table to EEPROM (only GW/repeaters) -* - TSF:MSG from @ref transportProcessMessage(), processes incoming message -* - TSF:SAN from @ref transportInvokeSanityCheck(), calls transport-specific sanity check -* - TSF:RTE from @ref transportRouteMessage(), sends message -* - TSF:SND from @ref transportSendRoute(), sends message if transport is ready (exposed) -* - TSF:TDI from @ref transportDisable() -* - TSF:TRI from @ref transportReInitialise() -* - TSF:SIR from @ref transportSignalReport() -* -* Transport debug log messages: -* -* |E| SYS | SUB | Message | Comment -* |-|-----|-------|---------------------------|--------------------------------------------------------------------- -* | | TSM | INIT | | Transition to stInit state -* | | TSM | INIT | STATID=%%d | Node ID is static -* | | TSM | INIT | TSP OK | Transport device configured and fully operational -* | | TSM | INIT | TSP PSM | Transport passive mode set -* | | TSM | INIT | GW MODE | Node is set up as GW, thus omitting ID and findParent states -* |!| TSM | INIT | TSP FAIL | Transport device initialization failed -* | | TSM | FPAR | | Transition to stParent state -* | | TSM | FPAR | STATP=%%d | Static parent set, skip finding parent -* | | TSM | FPAR | OK | Parent node identified -* |!| TSM | FPAR | NO REPLY | No potential parents replied to find parent request -* |!| TSM | FPAR | FAIL | Finding parent failed -* | | TSM | ID | | Transition to stID state -* | | TSM | ID | OK,ID=%%d | Node ID is valid -* | | TSM | ID | REQ | Request node ID from controller -* |!| TSM | ID | FAIL,ID=%%d | ID verification failed, ID invalid, no ID received from controller -* | | TSM | UPL | | Transition to stUplink state -* | | TSM | UPL | OK | Uplink OK, GW returned ping -* | | TSF | UPL | DGWC,O=%%d,N=%%d | Uplink check revealed changed network topology, old distance (O), new distance (N) -* |!| TSM | UPL | FAIL | Uplink check failed, i.e. GW could not be pinged -* | | TSM | READY | SRT | Save routing table -* | | TSM | READY | ID=%%d,PAR=%%d,DIS=%%d | Transition to stReady Transport ready, node ID (ID), parent node ID (PAR), distance to GW (DIS) -* |!| TSM | READY | UPL FAIL,SNP | Too many failed uplink transmissions, search new parent -* |!| TSM | READY | FAIL,STATP | Too many failed uplink transmissions, static parent enforced -* | | TSM | FAIL | CNT=%%d | Transition to stFailure state, consecutive failure counter (CNT) -* | | TSM | FAIL | DIS | Disable transport -* | | TSM | FAIL | RE-INIT | Attempt to re-initialize transport -* | | TSF | CKU | OK | Uplink OK -* | | TSF | CKU | OK,FCTRL | Uplink OK, flood control prevents pinging GW in too short intervals -* | | TSF | CKU | DGWC,O=%%d,N=%%d | Uplink check revealed changed network topology, old distance (O), new distance (N) -* | | TSF | CKU | FAIL | No reply received when checking uplink -* | | TSF | SID | OK,ID=%%d | Node ID assigned -* |!| TSF | SID | FAIL,ID=%%d | Assigned ID is invalid -* | | TSF | PNG | SEND,TO=%%d | Send ping to destination (TO) -* | | TSF | WUR | MS=%%lu | Wait until transport ready, timeout (MS) -* | | TSF | MSG | ECHO REQ | ECHO message requested -* | | TSF | MSG | ECHO | ECHO message, do not proceed but forward to callback -* | | TSF | MSG | FPAR RES,ID=%%d,D=%%d | Response to find parent received from node (ID) with distance (D) to GW -* | | TSF | MSG | FPAR PREF FOUND | Preferred parent found, i.e. parent defined via MY_PARENT_NODE_ID -* | | TSF | MSG | FPAR OK,ID=%%d,D=%%d | Find parent response from node (ID) is valid, distance (D) to GW -* | | TSF | MSG | FPAR INACTIVE | Find parent response received, but no find parent request active, skip response -* | | TSF | MSG | FPAR REQ,ID=%%d | Find parent request from node (ID) -* | | TSF | MSG | PINGED,ID=%%d,HP=%%d | Node pinged by node (ID) with (HP) hops -* | | TSF | MSG | PONG RECV,HP=%%d | Pinged node replied with (HP) hops -* | | TSF | MSG | BC | Broadcast message received -* | | TSF | MSG | GWL OK | Link to GW ok -* | | TSF | MSG | FWD BC MSG | Controlled broadcast message forwarding -* | | TSF | MSG | RCV CB | Hand over message to @ref receive() callback function -* | | TSF | MSG | REL MSG | Relay message -* | | TSF | MSG | REL PxNG,HP=%%d | Relay PING/PONG message, increment hop counter (HP) -* |!| TSF | MSG | SIGN VERIFY FAIL | Signing verification failed -* |!| TSF | MSG | REL MSG,NORP | Node received a message for relaying, but node is not a repeater, message skipped -* |!| TSF | MSG | SIGN FAIL | Signing message failed -* |!| TSF | MSG | GWL FAIL | GW uplink failed -* |!| TSF | MSG | ID TK INVALID | Token for ID request invalid -* | | TSF | SAN | OK | Sanity check passed -* |!| TSF | SAN | FAIL | Sanity check failed, attempt to re-initialize radio -* | | TSF | CRT | OK | Clearing routing table successful -* | | TSF | LRT | OK | Loading routing table successful -* | | TSF | SRT | OK | Saving routing table successful -* |!| TSF | RTE | FPAR ACTIVE | Finding parent active, message not sent -* |!| TSF | RTE | DST %%d UNKNOWN | Routing for destination (DST) unknown, send message to parent -* | | TSF | RTE | N2N OK | Node-to-node communication succeeded -* |!| TSF | RTE | N2N FAIL | Node-to-node communication failed, handing over to parent for re-routing -* | | TSF | RRT | ROUTE N=%%d,R=%%d | Routing table, messages to node (N) are routed via node (R) -* |!| TSF | SND | TNR | Transport not ready, message cannot be sent -* | | TSF | TDI | TSL | Set transport to sleep -* | | TSF | TDI | TPD | Power down transport -* | | TSF | TRI | TRI | Reinitialise transport -* | | TSF | TRI | TSB | Set transport to standby -* | | TSF | SIR | CMD=%d,VAL=%d | Get signal report -* -* -* Incoming / outgoing messages: -* -* See here for more detail on the format and definitions. -* -* Receiving a message -* - TSF:MSG:READ,sender-last-destination,s=%%d,c=%%d,t=%%d,pt=%%d,l=%%d,sg=%%d:%%s -* -* Sending a message -* - [!/?]TSF:MSG:SEND,sender-last-next-destination,s=%%d,c=%%d,t=%%d,pt=%%d,l=%%d,sg=%%d,ft=%%d,st=%%s:%%s -* -* Prepended char: -* - none=sending OK -* - !=error sending -* - ?=sending status unknown -* Message fields: -* - s=sensor ID -* - c=command -* - t=msg type -* - pt=payload type -* - l=length -* - sg=signing flag -* - ft=failed uplink transmission counter -* - st=send status, OK=success, NACK=no radio ACK received -* -* @startuml -* state top as "Transport" { -* state Init -* state Failure -* state Ready -* state Parent -* state ID -* state Uplink -* } -* -* [*] --> Init -* Init : entry / Read config from eeprom -* Init --> Failure : [! transportInit()\n|| ID == 0\n|| ID == 255 ] -* Init --> Ready : [MY_GATEWAY_FEATURE] -* Init --> Parent : [else] -* -* Parent : entry / Broadcast Find Parent -* Parent --> ID : [MY_PARENT_NODE_IS_STATIC\n|| MY_PASSIVE_NODE\n|| Parent found] -* Parent --> Parent : [timeout\n&& retries left] -* Parent --> Failure : [timeout\n&& no retries left] -* -* ID : entry / Request Node ID -* ID --> Uplink : [ID valid] -* ID --> ID : [timeout\n&& retries left] -* ID --> Failure : [timeout\n&& no retries left] -* -* Uplink : entry / Check uplink (PING) -* Uplink --> Uplink : [timeout\n&& retries left] -* Uplink --> Parent : [timeout\n&& no retries left] -* Uplink --> Ready : [MY_TRANSPORT_UPLINK_CHECK_DISABLED\n|| Uplink ok (PONG)] -* -* Ready : entry / Transport ready callback -* Ready : MY_GATEWAY_FEATURE && Network discovery required / Send discovery -* Ready --> Parent : [!MY_PARENT_NODE_IS_STATIC\n&& Uplink failure overflow] -* -* Failure : entry / Disable transport -* Failure --> Init : [timeout] -* top --> Failure : [MY_TRANSPORT_SANITY_CHECK\n&& !transportSanityCheck] -* @enduml -* -* @brief API declaration for MyTransport -* -*/ - -#ifndef MyTransport_h -#define MyTransport_h - -#include "hal/transport/MyTransportHAL.h" - -#ifndef MY_TRANSPORT_MAX_TX_FAILURES -#if defined(MY_REPEATER_FEATURE) -#define MY_TRANSPORT_MAX_TX_FAILURES (10u) //!< search for a new parent node after this many transmission failures, higher threshold for repeating nodes -#else -#define MY_TRANSPORT_MAX_TX_FAILURES (5u) //!< search for a new parent node after this many transmission failures, lower threshold for non-repeating nodes -#endif -#endif - -#ifndef MY_TRANSPORT_MAX_TSM_FAILURES -#define MY_TRANSPORT_MAX_TSM_FAILURES (7u) //!< Max. number of consecutive TSM failure state entries (3bits) -#endif - -#ifndef MY_TRANSPORT_TIMEOUT_FAILURE_STATE_MS -#define MY_TRANSPORT_TIMEOUT_FAILURE_STATE_MS (10*1000ul) //!< Duration failure state (in ms) -#endif -#ifndef MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE_MS -#define MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE_MS (60*1000ul) //!< Duration extended failure state (in ms) -#endif -#ifndef MY_TRANSPORT_STATE_TIMEOUT_MS -#define MY_TRANSPORT_STATE_TIMEOUT_MS (2*1000ul) //!< general state timeout (in ms) -#endif -#ifndef MY_TRANSPORT_CHKUPL_INTERVAL_MS -#define MY_TRANSPORT_CHKUPL_INTERVAL_MS (10*1000ul) //!< Interval to re-check uplink (in ms) -#endif -#ifndef MY_TRANSPORT_STATE_RETRIES -#define MY_TRANSPORT_STATE_RETRIES (3u) //!< retries before switching to FAILURE -#endif - -#define AUTO (255u) //!< ID 255 is reserved -#define BROADCAST_ADDRESS (255u) //!< broadcasts are addressed to ID 255 -#define DISTANCE_INVALID (255u) //!< invalid distance when searching for parent -#define MAX_HOPS (254u) //!< maximal number of hops for ping/pong -#define INVALID_HOPS (255u) //!< invalid hops -#define MAX_SUBSEQ_MSGS (5u) //!< Maximum number of subsequently processed messages in FIFO (to prevent transport deadlock if HW issue) -#define UPLINK_QUALITY_WEIGHT (0.05f) //!< UPLINK_QUALITY_WEIGHT - - -// parent node check -#if defined(MY_PARENT_NODE_IS_STATIC) && !defined(MY_PARENT_NODE_ID) -#error MY_PARENT_NODE_IS_STATIC but no MY_PARENT_NODE_ID defined! -#endif - -#define _autoFindParent (bool)(MY_PARENT_NODE_ID == AUTO) //!< returns true if static parent id is undefined -#define isValidDistance(_distance) (bool)(_distance!=DISTANCE_INVALID) //!< returns true if distance is valid -#define isValidParent(_parent) (bool)(_parent != AUTO) //!< returns true if parent is valid - -/** - * @brief Callback type - */ -typedef void(*transportCallback_t)(void); - -/** - * @brief Node configuration - * - * This structure stores node-related configurations - */ -typedef struct { - uint8_t nodeId; //!< Current node id - uint8_t parentNodeId; //!< Where this node sends its messages - uint8_t distanceGW; //!< This nodes distance to sensor net gateway (number of hops) - uint8_t passiveMode : 1; //!< Passive mode - uint8_t reserved : 7; //!< Reserved -} transportConfig_t; - -/** - * @brief SM state - * - * This structure stores SM state definitions - */ -typedef struct { - void(*Transition)(void); //!< state transition function - void(*Update)(void); //!< state update function -} transportState_t; -/** -* @brief Datatype for internal RSSI storage -*/ -typedef int16_t transportRSSI_t; //!< Datatype for internal RSSI storage - -// helper macro for conversion -#define transportInternalToRSSI(__value) ((int16_t)__value >> 4) //!< Convert internal RSSI to RSSI -#define transportRSSItoInternal(__value) ((transportRSSI_t)__value << 4) //!< Convert RSSI to internal RSSI - -/** - * @brief Status variables and SM state - * - * This structure stores transport status and SM variables - */ -typedef struct { - // SM variables - transportState_t *currentState; //!< pointer to current FSM state - uint32_t stateEnter; //!< state enter timepoint - // general transport variables - uint32_t lastUplinkCheck; //!< last uplink check, required to prevent GW flooding - // 8 bits - bool findingParentNode : 1; //!< flag finding parent node is active - bool preferredParentFound : 1; //!< flag preferred parent found - bool uplinkOk : 1; //!< flag uplink ok - bool pingActive : 1; //!< flag ping active - bool transportActive : 1; //!< flag transport active - uint8_t stateRetries : 3; //!< retries / state re-enter (max 7) - // 8 bits - uint8_t failedUplinkTransmissions : 4; //!< counter failed uplink transmissions (max 15) - uint8_t failureCounter : 3; //!< counter for TSM failures (max 7) - bool msgReceived : 1; //!< flag message received - uint8_t pingResponse; //!< stores I_PONG hops -#if defined(MY_SIGNAL_REPORT_ENABLED) - transportRSSI_t uplinkQualityRSSI; //!< Uplink quality, internal RSSI representation -#endif -} transportSM_t; - -/** -* @brief RAM routing table -*/ -typedef struct { - uint8_t route[SIZE_ROUTES]; //!< route for node -} routingTable_t; - -// PRIVATE functions - -/** -* @brief Initialize SM variables and transport HW -*/ -void stInitTransition(void); -/** -* @brief Initialize transport -*/ -void stInitUpdate(void); -/** -* @brief Find parent -*/ -void stParentTransition(void); -/** -* @brief Verify find parent responses -*/ -void stParentUpdate(void); -/** -* @brief Send ID request -*/ -void stIDTransition(void); -/** -* @brief Verify ID response and GW link -*/ -void stIDUpdate(void); -/** -* @brief Send uplink ping request -*/ -void stUplinkTransition(void); -/** -* @brief Verify uplink response -*/ -void stUplinkUpdate(void); -/** -* @brief Set transport OK -*/ -void stReadyTransition(void); -/** -* @brief Monitor transport link -*/ -void stReadyUpdate(void); -/** -* @brief Transport failure and power down radio -*/ -void stFailureTransition(void); -/** -* @brief Re-initialize transport after timeout -*/ -void stFailureUpdate(void); -/** -* @brief Switch SM state -* @param newState New state to switch SM to -*/ -void transportSwitchSM(transportState_t &newState); -/** -* @brief Update SM state -*/ -void transportUpdateSM(void); -/** -* @brief Request time in current SM state -* @return ms in current state -*/ -uint32_t transportTimeInState(void); -/** -* @brief Call transport driver sanity check -*/ -void transportInvokeSanityCheck(void); -/** -* @brief Process all pending messages in RX FIFO -*/ -void transportProcessFIFO(void); -/** -* @brief Receive message from RX FIFO and process -*/ -void transportProcessMessage(void); -/** -* @brief Assign node ID -* @param newNodeId New node ID -* @return true if node ID is valid and successfully assigned -*/ -bool transportAssignNodeID(const uint8_t newNodeId); -/** -* @brief Wait and process messages for a defined amount of time until specified message received -* @param waitingMS Time to wait and process incoming messages in ms -* @param cmd Specific command -* @param msgType Specific message type -* @return true if specified command received within waiting time -*/ -bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType); -/** -* @brief Ping node -* @param targetId Node to be pinged -* @return hops from pinged node or 255 if no answer received within 2000ms -*/ -uint8_t transportPingNode(const uint8_t targetId); -/** -* @brief Send and route message according to destination -* -* This function is used in MyTransport and omits the transport state check, i.e. message can be sent even if transport is not ready -* -* @param message -* @return true if message sent successfully -*/ -bool transportRouteMessage(MyMessage &message); -/** -* @brief Send and route message according to destination with transport state check -* @param message -* @return true if message sent successfully and false if sending error or transport !OK -*/ -bool transportSendRoute(MyMessage &message); -/** -* @brief Send message to recipient -* @param to Recipient of message -* @param message -* @return true if message sent successfully -*/ -bool transportSendWrite(const uint8_t to, MyMessage &message); -/** -* @brief Check uplink to GW, includes flooding control -* @param force to override flood control timer -* @return true if uplink ok -*/ -bool transportCheckUplink(const bool force = false); - -// PUBLIC functions - -/** -* @brief Wait until transport is ready -* @param waitingMS timeout in MS, set 0 (default) for no timeout, i.e. wait indefinitely. For a node in standalone mode (optional network connection) set >0 to allow a node entering the main loop() function. -* @return true if transport is ready -*/ -bool transportWaitUntilReady(const uint32_t waitingMS = 0); -/** -* @brief Initialize transport and SM -*/ -void transportInitialise(void); -/** -* @brief Process FIFO msg and update SM -*/ -void transportProcess(void); -/** -* @brief Flag transport ready -* @return true if transport is initialized and ready -*/ -bool isTransportReady(void); -/** -* @brief Flag searching parent ongoing -* @return true if transport is searching for parent -*/ -bool isTransportSearchingParent(void); -/** -* @brief Flag TSM extended failure -* @return true if TSM had too many consecutive failure state entries -*/ -bool isTransportExtendedFailure(void); -/** -* @brief Flag valid message received -* @return true if valid message received, needs to be reset if used -*/ -bool isMessageReceived(void); -/** -* @brief Reset message received flag -*/ -void resetMessageReceived(void); -/** -* @brief Clear routing table -*/ -void transportClearRoutingTable(void); -/** -* @brief Return heart beat -* @return MS in current state -*/ -uint32_t transportGetHeartbeat(void); -/** -* @brief Load routing table from EEPROM to RAM. -* Only for GW devices with enough RAM, i.e. ESP8266, RPI Sensebender GW, etc. -* Atmega328 has only limited amount of RAM -*/ -void transportLoadRoutingTable(void); -/** -* @brief Save routing table to EEPROM. -*/ -void transportSaveRoutingTable(void); -/** -* @brief Update routing table -* @param node -* @param route -*/ -void transportSetRoute(const uint8_t node, const uint8_t route); -/** -* @brief Load route to node -* @param node -* @return route to node -*/ -uint8_t transportGetRoute(const uint8_t node); -/** -* @brief Reports content of routing table -*/ -void transportReportRoutingTable(void); -/** -* @brief Get node ID -* @return node ID -*/ -uint8_t transportGetNodeId(void); -/** -* @brief Get parent node ID -* @return parent node ID -*/ -uint8_t transportGetParentNodeId(void); -/** -* @brief Get distance to GW -* @return distance (=hops) to GW -*/ -uint8_t transportGetDistanceGW(void); -/** -* @brief Toggle passive mode, i.e. transport does not wait for ACK -* @param OnOff -*/ -void transportTogglePassiveMode(const bool OnOff); -/** -* @brief Disable transport, if xxx_POWER_PIN is defined, transport is powered down, else send to sleep -*/ -void transportDisable(void); -/** -* @brief Reinitialise transport. Put transport to standby - If xxx_POWER_PIN set, power up and go to standby -*/ -void transportReInitialise(void); - -/** -* @brief Get transport signal report -* @param command: -* R = RSSI (if available) of incoming @ref I_SIGNAL_REPORT_REQUEST message (from last hop) -* R! = RSSI (if available) of ACK to @ref I_SIGNAL_REPORT_REVERSE message received from last hop -* S = SNR (if available) of incoming @ref I_SIGNAL_REPORT_REQUEST message (from last hop) -* S! = SNR (if available) of ACK to @ref I_SIGNAL_REPORT_REVERSE message received from last hop -* P = TX powerlevel in % -* T = TX powerlevel in dBm -* U = Uplink quality (via ACK from parent node), avg. RSSI -* @return Signal report (if report is not available, INVALID_RSSI, INVALID_SNR, INVALID_PERCENT, or INVALID_LEVEL is sent instead) -*/ -int16_t transportSignalReport(const char command) __attribute__((unused)); - -/** -* @brief Get transport signal report -* @param signalReport -* @return report -*/ -int16_t transportGetSignalReport(const signalReport_t signalReport) __attribute__((unused)); - -#endif // MyTransport_h -/** @}*/ diff --git a/lib/MySensors/core/Version.h b/lib/MySensors/core/Version.h deleted file mode 100644 index 4490778e..00000000 --- a/lib/MySensors/core/Version.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** -* @file Version.h -* -* @defgroup Versiongrp Version -* @ingroup internals -* @{ -* -* This file defines the MySensors library version number -* Please adjust for new releases. - -* These helper macros generate a numerical and alphanumerical (see http://www.semver.org) representation of the library version number, i.e -* -* | SemVer | Numerical | Comments -* |-------------|-------------|------------------ -* | 2.1.0 | 0x020100FF | final -* | 2.1.1-beta | 0x02010100 | first pre-release -* | 2.1.1 | 0x020101FF | final -* | 2.2.0-beta | 0x02020000 | first pre-release -* | 2.2.0-rc.1 | 0x02020001 | -* | 2.2.0-rc.2 | 0x02020002 | -* | 2.2.0 | 0x020200FF | final -*/ - -#ifndef Version_h -#define Version_h - -#define STR_HELPER(x) #x //!< Helper macro, STR_HELPER() -#define STR(x) STR_HELPER(x) //!< Helper macro, STR() - -#define MYSENSORS_LIBRARY_VERSION_MAJOR 2 //!< Major release version -#define MYSENSORS_LIBRARY_VERSION_MINOR 3 //!< Minor release version -#define MYSENSORS_LIBRARY_VERSION_PATCH 2 //!< Patch version -#define MYSENSORS_LIBRARY_VERSION_PRERELEASE "" //!< Pre-release suffix, i.e. alpha, beta, rc.1, etc -#define MYSENSORS_LIBRARY_VERSION_PRERELEASE_NUMBER 0xFF //!< incremental counter, starting at 0x00. 0xFF for final release - - -#if (MYSENSORS_LIBRARY_VERSION_PRERELEASE_NUMBER != 0xFF) -#define MYSENSORS_LIBRARY_VERSION STR(MYSENSORS_LIBRARY_VERSION_MAJOR) "." STR(MYSENSORS_LIBRARY_VERSION_MINOR) "." STR(MYSENSORS_LIBRARY_VERSION_PATCH) "-" MYSENSORS_LIBRARY_VERSION_PRERELEASE //!< pre-release versioning -#else -#define MYSENSORS_LIBRARY_VERSION STR(MYSENSORS_LIBRARY_VERSION_MAJOR) "." STR(MYSENSORS_LIBRARY_VERSION_MINOR) "." STR(MYSENSORS_LIBRARY_VERSION_PATCH) //!< final release versioning -#endif - -#define MYSENSORS_LIBRARY_VERSION_INT ( ((uint32_t)MYSENSORS_LIBRARY_VERSION_MAJOR) << 24 | ((uint32_t)MYSENSORS_LIBRARY_VERSION_MINOR) << 16 | ((uint32_t)MYSENSORS_LIBRARY_VERSION_PATCH) << 8 | ((uint32_t)MYSENSORS_LIBRARY_VERSION_PRERELEASE_NUMBER) ) //!< numerical versioning - -#endif // Version_h -/** @}*/ diff --git a/lib/MySensors/drivers/ATSHA204/ATSHA204.cpp b/lib/MySensors/drivers/ATSHA204/ATSHA204.cpp deleted file mode 100644 index 030b8eb5..00000000 --- a/lib/MySensors/drivers/ATSHA204/ATSHA204.cpp +++ /dev/null @@ -1,594 +0,0 @@ -#include "Arduino.h" -#include "ATSHA204.h" - -/* Local data and function prototypes */ - -static uint8_t device_pin; -#ifdef ARDUINO_ARCH_AVR -static volatile uint8_t *device_port_DDR, *device_port_OUT, *device_port_IN; -#endif -static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc); -static uint8_t sha204c_check_crc(uint8_t *response); -static void swi_set_signal_pin(uint8_t is_high); -static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer); -static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer); -static uint8_t swi_send_byte(uint8_t value); -static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response); -static uint8_t sha204c_resync(uint8_t size, uint8_t *response); -static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, - uint8_t execution_delay, uint8_t execution_timeout); - -/* SWI bit bang functions */ - -static void swi_set_signal_pin(uint8_t is_high) -{ - SHA204_SET_OUTPUT(); - - if (is_high) { - SHA204_POUT_HIGH(); - } else { - SHA204_POUT_LOW(); - } -} - -static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer) -{ - uint8_t i, bit_mask; - - // Disable interrupts while sending. - noInterrupts(); //swi_disable_interrupts(); - - // Set signal pin as output. - SHA204_POUT_HIGH(); - SHA204_SET_OUTPUT(); - - - // Wait turn around time. - delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; - - for (i = 0; i < count; i++) { - for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { - if (bit_mask & buffer[i]) { - SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; - delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; - } else { - // Send a zero bit. - SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; - delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5; - } - } - } - interrupts(); //swi_enable_interrupts(); - return SWI_FUNCTION_RETCODE_SUCCESS; -} - -static uint8_t swi_send_byte(uint8_t value) -{ - return swi_send_bytes(1, &value); -} - -static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer) -{ - uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS; - uint8_t i; - uint8_t bit_mask; - uint8_t pulse_count; - uint8_t timeout_count; - - // Disable interrupts while receiving. - noInterrupts(); //swi_disable_interrupts(); - - // Configure signal pin as input. - SHA204_SET_INPUT(); - - // Receive bits and store in buffer. - for (i = 0; i < count; i++) { - for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { - pulse_count = 0; - - // Make sure that the variable below is big enough. - // Change it to uint16_t if 255 is too small, but be aware that - // the loop resolution decreases on an 8-bit controller in that case. - timeout_count = START_PULSE_TIME_OUT; - - // Detect start bit. - while (--timeout_count > 0) { - // Wait for falling edge. - if (SHA204_PIN_READ() == 0) { - break; - } - } - - if (timeout_count == 0) { - status = SWI_FUNCTION_RETCODE_TIMEOUT; - break; - } - - do { - // Wait for rising edge. - if (SHA204_PIN_READ() != 0) { - // For an Atmel microcontroller this might be faster than "pulse_count++". - pulse_count = 1; - break; - } - } while (--timeout_count > 0); - - if (pulse_count == 0) { - status = SWI_FUNCTION_RETCODE_TIMEOUT; - break; - } - - // Trying to measure the time of start bit and calculating the timeout - // for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU. - // So let's just wait the maximum time for the falling edge of a zero bit - // to arrive after we have detected the rising edge of the start bit. - timeout_count = ZERO_PULSE_TIME_OUT; - - // Detect possible edge indicating zero bit. - do { - if (SHA204_PIN_READ() == 0) { - // For an Atmel microcontroller this might be faster than "pulse_count++". - pulse_count = 2; - break; - } - } while (--timeout_count > 0); - - // Wait for rising edge of zero pulse before returning. Otherwise we might interpret - // its rising edge as the next start pulse. - if (pulse_count == 2) { - do { - if (SHA204_PIN_READ() != 0) { - break; - } - } while (timeout_count-- > 0); - } - - // Update byte at current buffer index. - else { - buffer[i] |= bit_mask; // received "one" bit - } - } - - if (status != SWI_FUNCTION_RETCODE_SUCCESS) { - break; - } - } - interrupts(); //swi_enable_interrupts(); - - if (status == SWI_FUNCTION_RETCODE_TIMEOUT) { - if (i > 0) { - // Indicate that we timed out after having received at least one byte. - status = SWI_FUNCTION_RETCODE_RX_FAIL; - } - } - return status; -} - -/* Physical functions */ - -static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response) -{ - uint8_t i; - uint8_t ret_code; - - for (i = 0; i < size; i++) { - response[i] = 0; - } - - (void) swi_send_byte(SHA204_SWI_FLAG_TX); - - ret_code = swi_receive_bytes(size, response); - if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) { - uint8_t count_byte; - count_byte = response[SHA204_BUFFER_POS_COUNT]; - if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) { - return SHA204_INVALID_SIZE; - } - - return SHA204_SUCCESS; - } - - // Translate error so that the Communication layer - // can distinguish between a real error or the - // device being busy executing a command. - if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) { - return SHA204_RX_NO_RESPONSE; - } else { - return SHA204_RX_FAIL; - } -} - -/* Communication functions */ - -static uint8_t sha204c_resync(uint8_t size, uint8_t *response) -{ - // Try to re-synchronize without sending a Wake token - // (step 1 of the re-synchronization process). - delay(SHA204_SYNC_TIMEOUT); - uint8_t ret_code = sha204p_receive_response(size, response); - if (ret_code == SHA204_SUCCESS) { - return ret_code; - } - - // We lost communication. Send a Wake pulse and try - // to receive a response (steps 2 and 3 of the - // re-synchronization process). - atsha204_sleep(); - ret_code = atsha204_wakeup(response); - - // Translate a return value of success into one - // that indicates that the device had to be woken up - // and might have lost its TempKey. - return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); -} - -static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, - uint8_t execution_delay, uint8_t execution_timeout) -{ - uint8_t ret_code = SHA204_FUNC_FAIL; - uint8_t ret_code_resync; - uint8_t n_retries_send; - uint8_t n_retries_receive; - uint8_t i; - uint8_t status_byte; - uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT]; - uint8_t count_minus_crc = count - SHA204_CRC_SIZE; - uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT; - volatile uint16_t timeout_countdown; - - // Append CRC. - sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc); - - // Retry loop for sending a command and receiving a response. - n_retries_send = SHA204_RETRY_COUNT + 1; - - while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) { - // Send command. - ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); - if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) { - ret_code = SHA204_COMM_FAIL; - } else { - ret_code = swi_send_bytes(count, tx_buffer); - } - - if (ret_code != SHA204_SUCCESS) { - if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { - return ret_code; // The device seems to be dead in the water. - } else { - continue; - } - } - - // Wait minimum command execution time and then start polling for a response. - delay(execution_delay); - - // Retry loop for receiving a response. - n_retries_receive = SHA204_RETRY_COUNT + 1; - while (n_retries_receive-- > 0) { - // Reset response buffer. - for (i = 0; i < rx_size; i++) { - rx_buffer[i] = 0; - } - - // Poll for response. - timeout_countdown = execution_timeout_us; - do { - ret_code = sha204p_receive_response(rx_size, rx_buffer); - timeout_countdown -= SHA204_RESPONSE_TIMEOUT; - } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE)); - - if (ret_code == SHA204_RX_NO_RESPONSE) { - // We did not receive a response. Re-synchronize and send command again. - if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { - // The device seems to be dead in the water. - return ret_code; - } else { - break; - } - } - - // Check whether we received a valid response. - if (ret_code == SHA204_INVALID_SIZE) { - // We see 0xFF for the count when communication got out of sync. - ret_code_resync = sha204c_resync(rx_size, rx_buffer); - if (ret_code_resync == SHA204_SUCCESS) { - // We did not have to wake up the device. Try receiving response again. - continue; - } - if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) { - // We could re-synchronize, but only after waking up the device. - // Re-send command. - break; - } else { - // We failed to re-synchronize. - return ret_code; - } - } - - // We received a response of valid size. - // Check the consistency of the response. - ret_code = sha204c_check_crc(rx_buffer); - if (ret_code == SHA204_SUCCESS) { - // Received valid response. - if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) { - // Received non-status response. We are done. - return ret_code; - } - - // Received status response. - status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS]; - - // Translate the three possible device status error codes - // into library return codes. - if (status_byte == SHA204_STATUS_BYTE_PARSE) { - return SHA204_PARSE_ERROR; - } - if (status_byte == SHA204_STATUS_BYTE_EXEC) { - return SHA204_CMD_FAIL; - } - if (status_byte == SHA204_STATUS_BYTE_COMM) { - // In case of the device status byte indicating a communication - // error this function exits the retry loop for receiving a response - // and enters the overall retry loop - // (send command / receive response). - ret_code = SHA204_STATUS_CRC; - break; - } - - // Received status response from CheckMAC, DeriveKey, GenDig, - // Lock, Nonce, Pause, UpdateExtra, or Write command. - return ret_code; - } - - else { - // Received response with incorrect CRC. - ret_code_resync = sha204c_resync(rx_size, rx_buffer); - if (ret_code_resync == SHA204_SUCCESS) { - // We did not have to wake up the device. Try receiving response again. - continue; - } - if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) { - // We could re-synchronize, but only after waking up the device. - // Re-send command. - break; - } else { - // We failed to re-synchronize. - return ret_code; - } - } // block end of check response consistency - - } // block end of receive retry loop - - } // block end of send and receive retry loop - - return ret_code; -} - -/* CRC Calculator and Checker */ - -static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc) -{ - uint8_t counter; - uint16_t crc_register = 0; - uint16_t polynom = 0x8005; - uint8_t shift_register; - uint8_t data_bit, crc_bit; - - for (counter = 0; counter < length; counter++) { - for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { - data_bit = (data[counter] & shift_register) ? 1 : 0; - crc_bit = crc_register >> 15; - - // Shift CRC to the left by 1. - crc_register <<= 1; - - if ((data_bit ^ crc_bit) != 0) { - crc_register ^= polynom; - } - } - } - crc[0] = (uint8_t) (crc_register & 0x00FF); - crc[1] = (uint8_t) (crc_register >> 8); -} - -static uint8_t sha204c_check_crc(uint8_t *response) -{ - uint8_t crc[SHA204_CRC_SIZE]; - uint8_t count = response[SHA204_BUFFER_POS_COUNT]; - - count -= SHA204_CRC_SIZE; - sha204c_calculate_crc(count, response, crc); - - return (crc[0] == response[count] && crc[1] == response[count + 1]) - ? SHA204_SUCCESS : SHA204_BAD_CRC; -} - -/* Public functions */ - -void atsha204_init(uint8_t pin) -{ -#if defined(ARDUINO_ARCH_AVR) - device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin - uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers - - // Point to data direction register port of pin - device_port_DDR = portModeRegister(port); - // Point to output register of pin - device_port_OUT = portOutputRegister(port); - // Point to input register of pin - device_port_IN = portInputRegister(port); -#else - device_pin = pin; -#endif -} - -void atsha204_idle(void) -{ - swi_send_byte(SHA204_SWI_FLAG_IDLE); -} - -void atsha204_sleep(void) -{ - swi_send_byte(SHA204_SWI_FLAG_SLEEP); -} - -uint8_t atsha204_wakeup(uint8_t *response) -{ - swi_set_signal_pin(0); - delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH); - swi_set_signal_pin(1); - delay(SHA204_WAKEUP_DELAY); - - uint8_t ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response); - if (ret_code != SHA204_SUCCESS) { - return ret_code; - } - - // Verify status response. - if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) { - ret_code = SHA204_INVALID_SIZE; - } else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) { - ret_code = SHA204_COMM_FAIL; - } else { - if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) - || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) { - ret_code = SHA204_BAD_CRC; - } - } - if (ret_code != SHA204_SUCCESS) { - delay(SHA204_COMMAND_EXEC_MAX); - } - - return ret_code; -} - -uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, - uint8_t *rx_buffer) -{ - uint8_t poll_delay, poll_timeout, response_size; - uint8_t *p_buffer; - uint8_t len; - (void)tx_size; - - // Supply delays and response size. - switch (op_code) { - case SHA204_GENDIG: - poll_delay = GENDIG_DELAY; - poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; - response_size = GENDIG_RSP_SIZE; - break; - - case SHA204_HMAC: - poll_delay = HMAC_DELAY; - poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY; - response_size = HMAC_RSP_SIZE; - break; - - case SHA204_NONCE: - poll_delay = NONCE_DELAY; - poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY; - response_size = param1 == NONCE_MODE_PASSTHROUGH - ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG; - break; - - case SHA204_RANDOM: - poll_delay = RANDOM_DELAY; - poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY; - response_size = RANDOM_RSP_SIZE; - break; - - case SHA204_SHA: - poll_delay = SHA_DELAY; - poll_timeout = SHA_EXEC_MAX - SHA_DELAY; - response_size = param1 == SHA_INIT - ? SHA_RSP_SIZE_SHORT : SHA_RSP_SIZE_LONG; - break; - - case SHA204_WRITE: - poll_delay = WRITE_DELAY; - poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY; - response_size = WRITE_RSP_SIZE; - break; - - default: - poll_delay = 0; - poll_timeout = SHA204_COMMAND_EXEC_MAX; - response_size = rx_size; - } - - // Assemble command. - len = datalen1 + SHA204_CMD_SIZE_MIN; - p_buffer = tx_buffer; - *p_buffer++ = len; - *p_buffer++ = op_code; - *p_buffer++ = param1; - *p_buffer++ = param2 & 0xFF; - *p_buffer++ = param2 >> 8; - - if (datalen1 > 0) { - memcpy(p_buffer, data1, datalen1); - p_buffer += datalen1; - } - - sha204c_calculate_crc(len - SHA204_CRC_SIZE, tx_buffer, p_buffer); - - // Send command and receive response. - return sha204c_send_and_receive(&tx_buffer[0], response_size, - &rx_buffer[0], poll_delay, poll_timeout); -} - -uint8_t atsha204_getSerialNumber(uint8_t * response) -{ - uint8_t readCommand[READ_COUNT]; - uint8_t readResponse[READ_4_RSP_SIZE]; - - /* read from bytes 0->3 of config zone */ - uint8_t returnCode = atsha204_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03); - if (!returnCode) { - for (int i=0; i<4; i++) {// store bytes 0-3 into respones array - response[i] = readResponse[SHA204_BUFFER_POS_DATA+i]; - } - - /* read from bytes 8->11 of config zone */ - returnCode = atsha204_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN47); - - for (int i=4; i<8; i++) {// store bytes 4-7 of SN into response array - response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)]; - } - - if (!returnCode) { - /* Finally if last two reads were successful, read byte 8 of the SN */ - returnCode = atsha204_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8); - response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE - } - } - - return returnCode; -} - -uint8_t atsha204_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address) -{ - uint8_t rx_size; - - address >>= 2; - - tx_buffer[SHA204_COUNT_IDX] = READ_COUNT; - tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ; - tx_buffer[READ_ZONE_IDX] = zone; - tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK); - tx_buffer[READ_ADDR_IDX + 1] = 0; - - rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; - - return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, - READ_EXEC_MAX - READ_DELAY); -} diff --git a/lib/MySensors/drivers/ATSHA204/ATSHA204.h b/lib/MySensors/drivers/ATSHA204/ATSHA204.h deleted file mode 100644 index be27d5a7..00000000 --- a/lib/MySensors/drivers/ATSHA204/ATSHA204.h +++ /dev/null @@ -1,253 +0,0 @@ -#ifndef ATSHA204_H -#define ATSHA204_H -#if !DOXYGEN -#include - -/* This is a scaled down variant of the ATSHA204 library, tweaked to meet the specific needs of the MySensors library. */ - -/* Library return codes */ -#define SHA204_SUCCESS ((uint8_t) 0x00) //!< Function succeeded. -#define SHA204_PARSE_ERROR ((uint8_t) 0xD2) //!< response status byte indicates parsing error -#define SHA204_CMD_FAIL ((uint8_t) 0xD3) //!< response status byte indicates command execution error -#define SHA204_STATUS_CRC ((uint8_t) 0xD4) //!< response status byte indicates CRC error -#define SHA204_STATUS_UNKNOWN ((uint8_t) 0xD5) //!< response status byte is unknown -#define SHA204_FUNC_FAIL ((uint8_t) 0xE0) //!< Function could not execute due to incorrect condition / state. -#define SHA204_GEN_FAIL ((uint8_t) 0xE1) //!< unspecified error -#define SHA204_BAD_PARAM ((uint8_t) 0xE2) //!< bad argument (out of range, null pointer, etc.) -#define SHA204_INVALID_ID ((uint8_t) 0xE3) //!< invalid device id, id not set -#define SHA204_INVALID_SIZE ((uint8_t) 0xE4) //!< Count value is out of range or greater than buffer size. -#define SHA204_BAD_CRC ((uint8_t) 0xE5) //!< incorrect CRC received -#define SHA204_RX_FAIL ((uint8_t) 0xE6) //!< Timed out while waiting for response. Number of bytes received is > 0. -#define SHA204_RX_NO_RESPONSE ((uint8_t) 0xE7) //!< Not an error while the Command layer is polling for a command response. -#define SHA204_RESYNC_WITH_WAKEUP ((uint8_t) 0xE8) //!< re-synchronization succeeded, but only after generating a Wake-up - -#define SHA204_COMM_FAIL ((uint8_t) 0xF0) //!< Communication with device failed. Same as in hardware dependent modules. -#define SHA204_TIMEOUT ((uint8_t) 0xF1) //!< Timed out while waiting for response. Number of bytes received is 0. - -/* bitbang_config.h */ - -#define PORT_ACCESS_TIME (630) //! time it takes to toggle the pin at CPU clock of 16 MHz (ns) -#define START_PULSE_WIDTH (4340) //! width of start pulse (ns) -#define BIT_DELAY (4) //! delay macro for width of one pulse (start pulse or zero pulse, in ns) -#define RX_TX_DELAY (15) //! turn around time when switching from receive to transmit -#define START_PULSE_TIME_OUT (255) //! This value is decremented while waiting for the falling edge of a start pulse. -#define ZERO_PULSE_TIME_OUT (26) //! This value is decremented while waiting for the falling edge of a zero pulse. - -/* swi_phys.h */ - -#define SWI_FUNCTION_RETCODE_SUCCESS ((uint8_t) 0x00) //!< Communication with device succeeded. -#define SWI_FUNCTION_RETCODE_TIMEOUT ((uint8_t) 0xF1) //!< Communication timed out. -#define SWI_FUNCTION_RETCODE_RX_FAIL ((uint8_t) 0xF9) //!< Communication failed after at least one byte was received. - -/* sha204_physical.h */ - -#define SHA204_RSP_SIZE_MIN ((uint8_t) 4) //!< minimum number of bytes in response -#define SHA204_RSP_SIZE_MAX ((uint8_t) 35) //!< maximum size of response packet -#define SHA204_BUFFER_POS_COUNT (0) //!< buffer index of count byte in command or response -#define SHA204_BUFFER_POS_DATA (1) //!< buffer index of data in response -#define SHA204_WAKEUP_PULSE_WIDTH (uint8_t) (6.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! width of Wakeup pulse in 10 us units -#define SHA204_WAKEUP_DELAY (uint8_t) (3.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! delay between Wakeup pulse and communication in ms - -/* sha204_swi.c */ -#define SHA204_SWI_FLAG_CMD ((uint8_t) 0x77) //!< flag preceding a command -#define SHA204_SWI_FLAG_TX ((uint8_t) 0x88) //!< flag requesting a response -#define SHA204_SWI_FLAG_IDLE ((uint8_t) 0xBB) //!< flag requesting to go into Idle mode -#define SHA204_SWI_FLAG_SLEEP ((uint8_t) 0xCC) //!< flag requesting to go into Sleep mode - -/* sha204_comm_marshaling.h */ -// command op-code definitions -#define SHA204_GENDIG ((uint8_t) 0x15) //!< GenDig command op-code -#define SHA204_HMAC ((uint8_t) 0x11) //!< HMAC command op-code -#define SHA204_NONCE ((uint8_t) 0x16) //!< Nonce command op-code -#define SHA204_RANDOM ((uint8_t) 0x1B) //!< Random command op-code -#define SHA204_READ ((uint8_t) 0x02) //!< Read command op-code -#define SHA204_SHA ((uint8_t) 0x47) //!< SHA command op-code -#define SHA204_WRITE ((uint8_t) 0x12) //!< Write command op-code - -// packet size definitions -#define SHA204_RSP_SIZE_VAL ((uint8_t) 7) //!< size of response packet containing four bytes of data - -// definitions for command packet indexes common to all commands -#define SHA204_COUNT_IDX ( 0) //!< command packet index for count -#define SHA204_OPCODE_IDX ( 1) //!< command packet index for op-code -#define SHA204_PARAM1_IDX ( 2) //!< command packet index for first parameter -#define SHA204_PARAM2_IDX ( 3) //!< command packet index for second parameter -#define SHA204_DATA_IDX ( 5) //!< command packet index for second parameter - -// zone definitions -#define SHA204_ZONE_CONFIG ((uint8_t) 0x00) //!< Configuration zone -#define SHA204_ZONE_OTP ((uint8_t) 0x01) //!< OTP (One Time Programming) zone -#define SHA204_ZONE_DATA ((uint8_t) 0x02) //!< Data zone -#define SHA204_ZONE_MASK ((uint8_t) 0x03) //!< Zone mask -#define SHA204_ZONE_COUNT_FLAG ((uint8_t) 0x80) //!< Zone bit 7 set: Access 32 bytes, otherwise 4 bytes. -#define SHA204_ZONE_ACCESS_4 ((uint8_t) 4) //!< Read or write 4 bytes. -#define SHA204_ZONE_ACCESS_32 ((uint8_t) 32) //!< Read or write 32 bytes. -#define SHA204_ADDRESS_MASK_CONFIG ( 0x001F) //!< Address bits 5 to 7 are 0 for Configuration zone. -#define SHA204_ADDRESS_MASK_OTP ( 0x000F) //!< Address bits 4 to 7 are 0 for OTP zone. -#define SHA204_ADDRESS_MASK ( 0x007F) //!< Address bit 7 to 15 are always 0. - -// GenDig command definitions -#define GENDIG_ZONE_IDX SHA204_PARAM1_IDX //!< GenDig command index for zone -#define GENDIG_KEYID_IDX SHA204_PARAM2_IDX //!< GenDig command index for key id -#define GENDIG_DATA_IDX SHA204_DATA_IDX //!< GenDig command index for optional data -#define GENDIG_COUNT SHA204_CMD_SIZE_MIN //!< GenDig command packet size without "other data" -#define GENDIG_COUNT_DATA (11) //!< GenDig command packet size with "other data" -#define GENDIG_OTHER_DATA_SIZE (4) //!< GenDig size of "other data" -#define GENDIG_ZONE_CONFIG ((uint8_t) 0) //!< GenDig zone id config -#define GENDIG_ZONE_OTP ((uint8_t) 1) //!< GenDig zone id OTP -#define GENDIG_ZONE_DATA ((uint8_t) 2) //!< GenDig zone id data - -// HMAC command definitions -#define HMAC_MODE_IDX SHA204_PARAM1_IDX //!< HMAC command index for mode -#define HMAC_KEYID_IDX SHA204_PARAM2_IDX //!< HMAC command index for key id -#define HMAC_COUNT SHA204_CMD_SIZE_MIN //!< HMAC command packet size -#define HMAC_MODE_MASK ((uint8_t) 0x74) //!< HMAC mode bits 0, 1, 3, and 7 are 0. -#define HMAC_MODE_SOURCE_FLAG_MATCH ((uint8_t) 0x04) //!< HMAC mode bit 2: match TempKey.SourceFlag - -// Nonce command definitions -#define NONCE_MODE_IDX SHA204_PARAM1_IDX //!< Nonce command index for mode -#define NONCE_PARAM2_IDX SHA204_PARAM2_IDX //!< Nonce command index for 2. parameter -#define NONCE_INPUT_IDX SHA204_DATA_IDX //!< Nonce command index for input data -#define NONCE_COUNT_SHORT (27) //!< Nonce command packet size for 20 bytes of data -#define NONCE_COUNT_LONG (39) //!< Nonce command packet size for 32 bytes of data -#define NONCE_MODE_MASK ((uint8_t) 3) //!< Nonce mode bits 2 to 7 are 0. -#define NONCE_MODE_SEED_UPDATE ((uint8_t) 0x00) //!< Nonce mode: update seed -#define NONCE_MODE_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Nonce mode: do not update seed -#define NONCE_MODE_INVALID ((uint8_t) 0x02) //!< Nonce mode 2 is invalid. -#define NONCE_MODE_PASSTHROUGH ((uint8_t) 0x03) //!< Nonce mode: pass-through -#define NONCE_NUMIN_SIZE (20) //!< Nonce data length -#define NONCE_NUMIN_SIZE_PASSTHROUGH (32) //!< Nonce data length in pass-through mode (mode = 3) - -// Random command definitions -#define RANDOM_MODE_IDX SHA204_PARAM1_IDX //!< Random command index for mode -#define RANDOM_PARAM2_IDX SHA204_PARAM2_IDX //!< Random command index for 2. parameter -#define RANDOM_COUNT SHA204_CMD_SIZE_MIN //!< Random command packet size -#define RANDOM_SEED_UPDATE ((uint8_t) 0x00) //!< Random mode for automatic seed update -#define RANDOM_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Random mode for no seed update - -// Read command definitions -#define READ_ZONE_IDX SHA204_PARAM1_IDX //!< Read command index for zone -#define READ_ADDR_IDX SHA204_PARAM2_IDX //!< Read command index for address -#define READ_COUNT SHA204_CMD_SIZE_MIN //!< Read command packet size -#define READ_ZONE_MASK ((uint8_t) 0x83) //!< Read zone bits 2 to 6 are 0. -#define READ_ZONE_MODE_32_BYTES ((uint8_t) 0x80) //!< Read mode: 32 bytes - -// SHA command definitions -#define SHA_MODE_IDX SHA204_PARAM1_IDX //!< SHA command index for mode -#define SHA_PARAM2_IDX SHA204_PARAM2_IDX //!< SHA command index for 2. parameter -#define SHA_COUNT_SHORT SHA204_CMD_SIZE_MIN //!< SHA command packet size for init -#define SHA_COUNT_LONG (71) //!< SHA command packet size for calculation -#define SHA_MSG_SIZE (64) //!< SHA message data size -#define SHA_INIT ((uint8_t) 0x00) //!< SHA mode for init -#define SHA_CALC ((uint8_t) 0x01) //!< SHA mode for calculation - -// Write command definitions -#define WRITE_ZONE_IDX SHA204_PARAM1_IDX //!< Write command index for zone -#define WRITE_ADDR_IDX SHA204_PARAM2_IDX //!< Write command index for address -#define WRITE_VALUE_IDX SHA204_DATA_IDX //!< Write command index for data -#define WRITE_MAC_VS_IDX ( 9) //!< Write command index for MAC following short data -#define WRITE_MAC_VL_IDX (37) //!< Write command index for MAC following long data -#define WRITE_COUNT_SHORT (11) //!< Write command packet size with short data and no MAC -#define WRITE_COUNT_LONG (39) //!< Write command packet size with long data and no MAC -#define WRITE_COUNT_SHORT_MAC (43) //!< Write command packet size with short data and MAC -#define WRITE_COUNT_LONG_MAC (71) //!< Write command packet size with long data and MAC -#define WRITE_MAC_SIZE (32) //!< Write MAC size -#define WRITE_ZONE_MASK ((uint8_t) 0xC3) //!< Write zone bits 2 to 5 are 0. -#define WRITE_ZONE_WITH_MAC ((uint8_t) 0x40) //!< Write zone bit 6: write encrypted with MAC - -// Response size definitions -#define GENDIG_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of GenDig command -#define HMAC_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of HMAC command -#define NONCE_RSP_SIZE_SHORT SHA204_RSP_SIZE_MIN //!< response size of Nonce command with mode[0:1] = 3 -#define NONCE_RSP_SIZE_LONG SHA204_RSP_SIZE_MAX //!< response size of Nonce command -#define RANDOM_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Random command -#define READ_4_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of Read command when reading 4 bytes -#define READ_32_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Read command when reading 32 bytes -#define SHA_RSP_SIZE_SHORT SHA204_RSP_SIZE_MIN //!< response size of SHA command with mode[0:1] = 0 -#define SHA_RSP_SIZE_LONG SHA204_RSP_SIZE_MAX //!< response size of SHA command -#define WRITE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Write command - -// command timing definitions for minimum execution times (ms) -#define GENDIG_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define HMAC_DELAY ((uint8_t) (27.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define NONCE_DELAY ((uint8_t) (22.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define RANDOM_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define READ_DELAY ((uint8_t) ( 0.4 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define SHA_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define WRITE_DELAY ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) - -// command timing definitions for maximum execution times (ms) -#define GENDIG_EXEC_MAX ((uint8_t) (43.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define HMAC_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define NONCE_EXEC_MAX ((uint8_t) (60.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define RANDOM_EXEC_MAX ((uint8_t) (50.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define READ_EXEC_MAX ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define SHA_EXEC_MAX ((uint8_t) (22.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define WRITE_EXEC_MAX ((uint8_t) (42.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) - -/* from sha204_config.h */ - -#define CPU_CLOCK_DEVIATION_POSITIVE (1.01) -#define CPU_CLOCK_DEVIATION_NEGATIVE (0.99) -#define SHA204_RETRY_COUNT (1) -#define SWI_RECEIVE_TIME_OUT ((uint16_t) 163) //! #START_PULSE_TIME_OUT in us instead of loop counts -#define SWI_US_PER_BYTE ((uint16_t) 313) //! It takes 312.5 us to send a byte (9 single-wire bits / 230400 Baud * 8 flag bits). -#define SHA204_SYNC_TIMEOUT ((uint8_t) 85)//! delay before sending a transmit flag in the synchronization routine -#define SHA204_RESPONSE_TIMEOUT ((uint16_t) SWI_RECEIVE_TIME_OUT + SWI_US_PER_BYTE) //! SWI response timeout is the sum of receive timeout and the time it takes to send the TX flag. - -/* from sha204_comm.h */ - -#define SHA204_COMMAND_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) //! maximum command delay -#define SHA204_CMD_SIZE_MIN ((uint8_t) 7) //! minimum number of bytes in command (from count byte to second CRC byte) -#ifndef SHA204_CMD_SIZE_MAX -#define SHA204_CMD_SIZE_MAX ((uint8_t) SHA_COUNT_LONG) //! maximum size of command packet (SHA) -#endif -#define SHA204_CRC_SIZE ((uint8_t) 2) //! number of CRC bytes -#define SHA204_BUFFER_POS_STATUS (1) //! buffer index of status byte in status response -#define SHA204_BUFFER_POS_DATA (1) //! buffer index of first data byte in data response -#define SHA204_STATUS_BYTE_WAKEUP ((uint8_t) 0x11) //! command parse error -#define SHA204_STATUS_BYTE_PARSE ((uint8_t) 0x03) //! command parse error -#define SHA204_STATUS_BYTE_EXEC ((uint8_t) 0x0F) //! command execution error -#define SHA204_STATUS_BYTE_COMM ((uint8_t) 0xFF) //! communication error - -/* EEPROM Addresses */ -/* Configuration Zone */ -#define ADDRESS_SN03 0 // SN[0:3] are bytes 0->3 of configuration zone -#define ADDRESS_RevNum 4 // bytes 4->7 of config zone are RevNum -#define ADDRESS_SN47 8 // SN[4:7] are bytes 8->11 of config zone -#define ADDRESS_SN8 12 // SN[8] is byte 12 of config zone, should be 0xEE -#define ADDRESS_I2CEN 14 // I2C Enable, bit 0 represents I2C enable status -#define ADDRESS_I2CADD 16 // Defines I2C address of SHA204 -#define ADDRESS_OTPMODE 18 // Sets the One-time-programmable mode -#define ADDRESS_SELECTOR 19 // Controls writability of Selector - -#define SHA204_SERIAL_SZ 9 // The number of bytes the serial number consists of - -/* Low level HW access macros */ -/* function calls is not working, as it will have too much overhead */ -#if !defined(ARDUINO_ARCH_AVR) // For everything else than AVR use pinMode / digitalWrite -#define SHA204_SET_OUTPUT() pinMode(device_pin, OUTPUT) -#define SHA204_SET_INPUT() pinMode(device_pin, INPUT) -#define SHA204_POUT_HIGH() digitalWrite(device_pin, HIGH) -#define SHA204_POUT_LOW() digitalWrite(device_pin, LOW) -#define SHA204_PIN_READ() digitalRead(device_pin) -#else -#define SHA204_SET_INPUT() *device_port_DDR &= ~device_pin -#define SHA204_SET_OUTPUT() *device_port_DDR |= device_pin -#define SHA204_POUT_HIGH() *device_port_OUT |= device_pin -#define SHA204_POUT_LOW() *device_port_OUT &= ~device_pin -#define SHA204_PIN_READ() (*device_port_IN & device_pin) -#endif - -void atsha204_init(uint8_t pin); -void atsha204_idle(void); -void atsha204_sleep(void); -uint8_t atsha204_wakeup(uint8_t *response); -uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t tx_size, - uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); -uint8_t atsha204_getSerialNumber(uint8_t *response); -uint8_t atsha204_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address); - -#endif -#endif diff --git a/lib/MySensors/drivers/AltSoftSerial/AltSoftSerial.cpp b/lib/MySensors/drivers/AltSoftSerial/AltSoftSerial.cpp deleted file mode 100644 index 94d94e1a..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/AltSoftSerial.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* An Alternative Software Serial Library - * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html - * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com - * - * 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. - */ - -// Revisions are now tracked on GitHub -// https://github.com/PaulStoffregen/AltSoftSerial -// -// Version 1.2: Support Teensy 3.x -// -// Version 1.1: Improve performance in receiver code -// -// Version 1.0: Initial Release - - -#include "AltSoftSerial.h" -#include "config/AltSoftSerial_Boards.h" -#include "config/AltSoftSerial_Timers.h" - -/****************************************/ -/** Initialization **/ -/****************************************/ - -static uint16_t ticks_per_bit=0; -bool AltSoftSerial::timing_error=false; - -static uint8_t rx_state; -static uint8_t rx_byte; -static uint8_t rx_bit = 0; -static uint16_t rx_target; -static uint16_t rx_stop_ticks=0; -static volatile uint8_t rx_buffer_head; -static volatile uint8_t rx_buffer_tail; -#define RX_BUFFER_SIZE 80 -static volatile uint8_t rx_buffer[RX_BUFFER_SIZE]; - -static volatile uint8_t tx_state=0; -static uint8_t tx_byte; -static uint8_t tx_bit; -static volatile uint8_t tx_buffer_head; -static volatile uint8_t tx_buffer_tail; -#define TX_BUFFER_SIZE 68 -static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; - - -#ifndef INPUT_PULLUP -#define INPUT_PULLUP INPUT -#endif - -#define MAX_COUNTS_PER_BIT 6241 // 65536 / 10.5 - -void AltSoftSerial::init(uint32_t cycles_per_bit) -{ - //Serial.printf("cycles_per_bit = %d\n", cycles_per_bit); - if (cycles_per_bit < MAX_COUNTS_PER_BIT) { - CONFIG_TIMER_NOPRESCALE(); - } else { - cycles_per_bit /= 8; - //Serial.printf("cycles_per_bit/8 = %d\n", cycles_per_bit); - if (cycles_per_bit < MAX_COUNTS_PER_BIT) { - CONFIG_TIMER_PRESCALE_8(); - } else { -#if defined(CONFIG_TIMER_PRESCALE_256) - cycles_per_bit /= 32; - //Serial.printf("cycles_per_bit/256 = %d\n", cycles_per_bit); - if (cycles_per_bit < MAX_COUNTS_PER_BIT) { - CONFIG_TIMER_PRESCALE_256(); - } else { - return; // baud rate too low for AltSoftSerial - } -#elif defined(CONFIG_TIMER_PRESCALE_128) - cycles_per_bit /= 16; - //Serial.printf("cycles_per_bit/128 = %d\n", cycles_per_bit); - if (cycles_per_bit < MAX_COUNTS_PER_BIT) { - CONFIG_TIMER_PRESCALE_128(); - } else { - return; // baud rate too low for AltSoftSerial - } -#else - return; // baud rate too low for AltSoftSerial -#endif - } - } - ticks_per_bit = cycles_per_bit; - rx_stop_ticks = cycles_per_bit * 37 / 4; - hwPinMode(INPUT_CAPTURE_PIN, INPUT_PULLUP); - hwDigitalWrite(OUTPUT_COMPARE_A_PIN, HIGH); - hwPinMode(OUTPUT_COMPARE_A_PIN, OUTPUT); - rx_state = 0; - rx_buffer_head = 0; - rx_buffer_tail = 0; - tx_state = 0; - tx_buffer_head = 0; - tx_buffer_tail = 0; - ENABLE_INT_INPUT_CAPTURE(); -} - -void AltSoftSerial::end(void) -{ - DISABLE_INT_COMPARE_B(); - DISABLE_INT_INPUT_CAPTURE(); - flushInput(); - flushOutput(); - DISABLE_INT_COMPARE_A(); - // TODO: restore timer to original settings? -} - - -/****************************************/ -/** Transmission **/ -/****************************************/ - -void AltSoftSerial::writeByte(uint8_t b) -{ - uint8_t intr_state, head; - - head = tx_buffer_head + 1; - if (head >= TX_BUFFER_SIZE) { - head = 0; - } - while (tx_buffer_tail == head) ; // wait until space in buffer - intr_state = SREG; - cli(); - if (tx_state) { - tx_buffer[head] = b; - tx_buffer_head = head; - } else { - tx_state = 1; - tx_byte = b; - tx_bit = 0; - ENABLE_INT_COMPARE_A(); - CONFIG_MATCH_CLEAR(); - SET_COMPARE_A(GET_TIMER_COUNT() + 16); - } - SREG = intr_state; -} - - -ISR(COMPARE_A_INTERRUPT) -{ - uint8_t state, byte, bit, head, tail; - uint16_t target; - - state = tx_state; - byte = tx_byte; - target = GET_COMPARE_A(); - while (state < 10) { - target += ticks_per_bit; - if (state < 9) { - bit = byte & 1; - } else { - bit = 1; // stopbit - } - byte >>= 1; - state++; - if (bit != tx_bit) { - if (bit) { - CONFIG_MATCH_SET(); - } else { - CONFIG_MATCH_CLEAR(); - } - SET_COMPARE_A(target); - tx_bit = bit; - tx_byte = byte; - tx_state = state; - // TODO: how to detect timing_error? - return; - } - } - head = tx_buffer_head; - tail = tx_buffer_tail; - if (head == tail) { - if (state == 10) { - // Wait for final stop bit to finish - tx_state = 11; - SET_COMPARE_A(target + ticks_per_bit); - } else { - tx_state = 0; - CONFIG_MATCH_NORMAL(); - DISABLE_INT_COMPARE_A(); - } - } else { - if (++tail >= TX_BUFFER_SIZE) { - tail = 0; - } - tx_buffer_tail = tail; - tx_byte = tx_buffer[tail]; - tx_bit = 0; - CONFIG_MATCH_CLEAR(); - if (state == 10) { - SET_COMPARE_A(target + ticks_per_bit); - } else { - SET_COMPARE_A(GET_TIMER_COUNT() + 16); - } - tx_state = 1; - // TODO: how to detect timing_error? - } -} - -void AltSoftSerial::flushOutput(void) -{ - while (tx_state) /* wait */ ; -} - - -/****************************************/ -/** Reception **/ -/****************************************/ - -ISR(CAPTURE_INTERRUPT) -{ - uint8_t state, bit; - uint16_t capture; - - capture = GET_INPUT_CAPTURE(); - bit = rx_bit; - if (bit) { - CONFIG_CAPTURE_FALLING_EDGE(); - rx_bit = 0; - } else { - CONFIG_CAPTURE_RISING_EDGE(); - rx_bit = 0x80; - } - state = rx_state; - if (state == 0) { - if (!bit) { - uint16_t end = capture + rx_stop_ticks; - SET_COMPARE_B(end); - ENABLE_INT_COMPARE_B(); - rx_target = capture + ticks_per_bit + ticks_per_bit/2; - rx_state = 1; - } - } else { - uint16_t target = rx_target; - const uint16_t offset_overflow = 65535 - ticks_per_bit; - while (1) { - const uint16_t offset = capture - target; - if (offset > offset_overflow) { - break; - } - rx_byte = (rx_byte >> 1) | rx_bit; - target += ticks_per_bit; - state++; - if (state >= 9) { - DISABLE_INT_COMPARE_B(); - uint8_t head = rx_buffer_head + 1; - if (head >= RX_BUFFER_SIZE) { - head = 0; - } - if (head != rx_buffer_tail) { - rx_buffer[head] = rx_byte; - rx_buffer_head = head; - } - CONFIG_CAPTURE_FALLING_EDGE(); - rx_bit = 0; - rx_state = 0; - return; - } - } - rx_target = target; - rx_state = state; - } - //if (GET_TIMER_COUNT() - capture > ticks_per_bit) AltSoftSerial::timing_error = true; -} - -ISR(COMPARE_B_INTERRUPT) -{ - uint8_t head, state, bit; - - DISABLE_INT_COMPARE_B(); - CONFIG_CAPTURE_FALLING_EDGE(); - state = rx_state; - bit = rx_bit ^ 0x80; - while (state < 9) { - rx_byte = (rx_byte >> 1) | bit; - state++; - } - head = rx_buffer_head + 1; - if (head >= RX_BUFFER_SIZE) { - head = 0; - } - if (head != rx_buffer_tail) { - rx_buffer[head] = rx_byte; - rx_buffer_head = head; - } - rx_state = 0; - CONFIG_CAPTURE_FALLING_EDGE(); - rx_bit = 0; -} - - - -int AltSoftSerial::read(void) -{ - uint8_t head, tail, out; - - head = rx_buffer_head; - tail = rx_buffer_tail; - if (head == tail) { - return -1; - } - if (++tail >= RX_BUFFER_SIZE) { - tail = 0; - } - out = rx_buffer[tail]; - rx_buffer_tail = tail; - return out; -} - -int AltSoftSerial::peek(void) -{ - uint8_t head, tail; - - head = rx_buffer_head; - tail = rx_buffer_tail; - if (head == tail) { - return -1; - } - if (++tail >= RX_BUFFER_SIZE) { - tail = 0; - } - return rx_buffer[tail]; -} - -int AltSoftSerial::available(void) -{ - uint8_t head, tail; - - head = rx_buffer_head; - tail = rx_buffer_tail; - if (head >= tail) { - return head - tail; - } - return RX_BUFFER_SIZE + head - tail; -} - -void AltSoftSerial::flushInput(void) -{ - rx_buffer_head = rx_buffer_tail; -} - - -#ifdef ALTSS_USE_FTM0 -void ftm0_isr(void) -{ - uint32_t flags = FTM0_STATUS; - FTM0_STATUS = 0; - if (flags & (1<<0) && (FTM0_C0SC & 0x40)) { - altss_compare_b_interrupt(); - } - if (flags & (1<<5)) { - altss_capture_interrupt(); - } - if (flags & (1<<6) && (FTM0_C6SC & 0x40)) { - altss_compare_a_interrupt(); - } -} -#endif - diff --git a/lib/MySensors/drivers/AltSoftSerial/AltSoftSerial.h b/lib/MySensors/drivers/AltSoftSerial/AltSoftSerial.h deleted file mode 100644 index ba8ebe0f..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/AltSoftSerial.h +++ /dev/null @@ -1,117 +0,0 @@ -/* An Alternative Software Serial Library - * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html - * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com - * - * 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. - */ - -#ifndef AltSoftSerial_h -#define AltSoftSerial_h - -#include - -#if ARDUINO >= 100 -#include "Arduino.h" -#else -#include "WProgram.h" -#include "pins_arduino.h" -#endif - -#if defined(__arm__) && defined(CORE_TEENSY) -#define ALTSS_BASE_FREQ F_BUS -#else -#define ALTSS_BASE_FREQ F_CPU -#endif - -/** AltSoftSerial class */ -class AltSoftSerial : public Stream -{ -public: - AltSoftSerial() { } //!< Constructor - ~AltSoftSerial() - { - end(); //!< Destructor - } - static void begin(uint32_t baud) - { - init((ALTSS_BASE_FREQ + baud / 2) / baud); //!< begin - } - static void end(); //!< end - int peek(); //!< peek - int read(); //!< read - int available(); //!< available -#if ARDUINO >= 100 - size_t write(uint8_t byte) - { - writeByte(byte); //!< write - return 1; - } - void flush() - { - flushOutput(); //!< flush - } -#else - void write(uint8_t byte) - { - writeByte(byte); //!< write - } - void flush() - { - flushInput(); //!< flush - } -#endif - using Print::write; - static void flushInput(); //!< flushInput - static void flushOutput(); //!< flushOutput - // for drop-in compatibility with NewSoftSerial, rxPin & txPin ignored - AltSoftSerial(uint8_t rxPin, uint8_t txPin, bool inverse = false) - { - (void)rxPin; //!< AltSoftSerial - (void)txPin; - (void)inverse; - } - bool listen() - { - return false; //!< listen - } - bool isListening() - { - return true; //!< isListening - } - bool overflow() - { - bool r = timing_error; //!< overflow - timing_error = false; - return r; - } - static int library_version() - { - return 1; //!< library_version - } - static void enable_timer0(bool enable) - { - (void)enable; //!< enable_timer0 - } - static bool timing_error; //!< timing_error -private: - static void init(uint32_t cycles_per_bit); - static void writeByte(uint8_t byte); -}; - -#endif diff --git a/lib/MySensors/drivers/AltSoftSerial/README.md b/lib/MySensors/drivers/AltSoftSerial/README.md deleted file mode 100644 index 376b2e37..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# AltSoftSerial Library - -Improved software emulated serial, using hardware timers for precise signal -timing and availability of CPU time for other libraries to respond to interrupts -during data AltSoftSerial data transmission and reception. - -http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html - -![AltSoftSerial on Teensy 2.0](http://www.pjrc.com/teensy/td_libs_AltSoftSerial_2.jpg) diff --git a/lib/MySensors/drivers/AltSoftSerial/config/AltSoftSerial_Boards.h b/lib/MySensors/drivers/AltSoftSerial/config/AltSoftSerial_Boards.h deleted file mode 100644 index 19fcd22c..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/config/AltSoftSerial_Boards.h +++ /dev/null @@ -1,147 +0,0 @@ -/* An Alternative Software Serial Library - * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html - * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com - * - * 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. - */ - - -// Teensy 2.0 -// -#if defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) - -//#define ALTSS_USE_TIMER1 -//#define INPUT_CAPTURE_PIN 22 // receive -//#define OUTPUT_COMPARE_A_PIN 14 // transmit -//#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM -//#define OUTPUT_COMPARE_C_PIN 4 // unusable PWM - -#define ALTSS_USE_TIMER3 -#define INPUT_CAPTURE_PIN 10 // receive -#define OUTPUT_COMPARE_A_PIN 9 // transmit - - - -// Teensy++ 2.0 -// -#elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY) - -#define ALTSS_USE_TIMER1 -#define INPUT_CAPTURE_PIN 4 // receive -#define OUTPUT_COMPARE_A_PIN 25 // transmit -#define OUTPUT_COMPARE_B_PIN 26 // unusable PWM -#define OUTPUT_COMPARE_C_PIN 27 // unusable PWM - -//#define ALTSS_USE_TIMER3 -//#define INPUT_CAPTURE_PIN 17 // receive -//#define OUTPUT_COMPARE_A_PIN 16 // transmit -//#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM -//#define OUTPUT_COMPARE_C_PIN 14 // unusable PWM - - -// Teensy 3.x -// -#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) -#define ALTSS_USE_FTM0 -#define INPUT_CAPTURE_PIN 20 // receive (FTM0_CH5) -#define OUTPUT_COMPARE_A_PIN 21 // transmit (FTM0_CH6) -#define OUTPUT_COMPARE_B_PIN 22 // unusable PWM (FTM0_CH0) -#define OUTPUT_COMPARE_C_PIN 23 // PWM usable fixed freq -#define OUTPUT_COMPARE_D_PIN 5 // PWM usable fixed freq -#define OUTPUT_COMPARE_E_PIN 6 // PWM usable fixed freq -#define OUTPUT_COMPARE_F_PIN 9 // PWM usable fixed freq -#define OUTPUT_COMPARE_G_PIN 10 // PWM usable fixed freq - - -// Wiring-S -// -#elif defined(__AVR_ATmega644P__) && defined(WIRING) - -#define ALTSS_USE_TIMER1 -#define INPUT_CAPTURE_PIN 6 // receive -#define OUTPUT_COMPARE_A_PIN 5 // transmit -#define OUTPUT_COMPARE_B_PIN 4 // unusable PWM - - - -// Arduino Uno, Duemilanove, LilyPad, etc -// -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - -#define ALTSS_USE_TIMER1 -#define INPUT_CAPTURE_PIN 8 // receive -#define OUTPUT_COMPARE_A_PIN 9 // transmit -#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM - - -// Arduino Leonardo & Yun (from Cristian Maglie) -// -#elif defined(ARDUINO_AVR_YUN) || defined(ARDUINO_AVR_LEONARDO) || defined(__AVR_ATmega32U4__) - -//#define ALTSS_USE_TIMER1 -//#define INPUT_CAPTURE_PIN 4 // receive -//#define OUTPUT_COMPARE_A_PIN 9 // transmit -//#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM -//#define OUTPUT_COMPARE_C_PIN 11 // unusable PWM - -#define ALTSS_USE_TIMER3 -#define INPUT_CAPTURE_PIN 13 // receive -#define OUTPUT_COMPARE_A_PIN 5 // transmit - - -// Arduino Mega -// -#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - -//#define ALTSS_USE_TIMER4 -//#define INPUT_CAPTURE_PIN 49 // receive -//#define OUTPUT_COMPARE_A_PIN 6 // transmit -//#define OUTPUT_COMPARE_B_PIN 7 // unusable PWM -//#define OUTPUT_COMPARE_C_PIN 8 // unusable PWM - -#define ALTSS_USE_TIMER5 -#define INPUT_CAPTURE_PIN 48 // receive -#define OUTPUT_COMPARE_A_PIN 46 // transmit -#define OUTPUT_COMPARE_B_PIN 45 // unusable PWM -#define OUTPUT_COMPARE_C_PIN 44 // unusable PWM - - - -// EnviroDIY Mayfly, Sodaq Mbili -#elif defined ARDUINO_AVR_ENVIRODIY_MAYFLY || defined ARDUINO_AVR_SODAQ_MBILI -#define ALTSS_USE_TIMER1 -#define INPUT_CAPTURE_PIN 6 // receive -#define OUTPUT_COMPARE_A_PIN 5 // transmit -#define OUTPUT_COMPARE_B_PIN 4 // unusable PWM - - - -// Sanguino, Mighty 1284 -#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__) -#define ALTSS_USE_TIMER1 -#define INPUT_CAPTURE_PIN 14 // receive -#define OUTPUT_COMPARE_A_PIN 13 // transmit -#define OUTPUT_COMPARE_B_PIN 12 // unusable PWM - - - -// Unknown board -#else -#error "Please define your board timer and pins" -#endif diff --git a/lib/MySensors/drivers/AltSoftSerial/config/AltSoftSerial_Timers.h b/lib/MySensors/drivers/AltSoftSerial/config/AltSoftSerial_Timers.h deleted file mode 100644 index 3ad18d7c..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/config/AltSoftSerial_Timers.h +++ /dev/null @@ -1,187 +0,0 @@ -/* An Alternative Software Serial Library - * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html - * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com - * - * 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. - */ - -#if defined(ALTSS_USE_TIMER1) -#define CONFIG_TIMER_NOPRESCALE() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1< Boards > Board Manager) -Operating system & version -Any other software or hardware? - - -### Arduino Sketch - -```cpp -// Change the code below by your sketch (please try to give the smallest code which demonstrates the problem) -#include - -// libraries: give links/details so anyone can compile your code for the same result - -void setup() { -} - -void loop() { -} -``` - - -### Errors or Incorrect Output - -If you see any errors or incorrect output, please show it here. Please use copy & paste to give an exact copy of the message. Details matter, so please show (not merely describe) the actual message or error exactly as it appears. - - diff --git a/lib/MySensors/drivers/AltSoftSerial/examples/Echo/Echo.ino b/lib/MySensors/drivers/AltSoftSerial/examples/Echo/Echo.ino deleted file mode 100644 index b6d5e395..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/examples/Echo/Echo.ino +++ /dev/null @@ -1,40 +0,0 @@ -#include - -// AltSoftSerial always uses these pins: -// -// Board Transmit Receive PWM Unusable -// ----- -------- ------- ------------ -// Teensy 3.0 & 3.1 21 20 22 -// Teensy 2.0 9 10 (none) -// Teensy++ 2.0 25 4 26, 27 -// Arduino Uno 9 8 10 -// Arduino Leonardo 5 13 (none) -// Arduino Mega 46 48 44, 45 -// Wiring-S 5 6 4 -// Sanguino 13 14 12 - -// This example code is in the public domain. - -AltSoftSerial altSerial; - -void setup() { - Serial.begin(9600); - while (!Serial) ; // wait for Arduino Serial Monitor to open - Serial.println("AltSoftSerial Test Begin"); - altSerial.begin(9600); - altSerial.println("Hello World"); -} - -void loop() { - char c; - - if (Serial.available()) { - c = Serial.read(); - altSerial.print(c); - } - if (altSerial.available()) { - c = altSerial.read(); - Serial.print(c); - } -} - diff --git a/lib/MySensors/drivers/AltSoftSerial/examples/ReceiveTest/ReceiveTest.ino b/lib/MySensors/drivers/AltSoftSerial/examples/ReceiveTest/ReceiveTest.ino deleted file mode 100644 index f3c1adb2..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/examples/ReceiveTest/ReceiveTest.ino +++ /dev/null @@ -1,56 +0,0 @@ -// AltSoftSerial Receive Test -// -// Transmit data with Serial1 and try to receive -// it with AltSoftSerial. You must connect a wire -// from Serial1 TX to AltSoftSerial RX. - -#include - -AltSoftSerial altser; -const int mybaud = 9600; - -// Board Serial1 TX AltSoftSerial RX -// ----- ---------- ---------------- -// Teensy 3.x 1 20 -// Teensy 2.0 8 (D3) 10 (C7) -// Teensy++ 2.0 3 (D3) 4 (D4) -// Arduino Leonardo 1 13 -// Arduino Mega 18 48 - -// Serial1 on AVR @ 16 MHz minimum baud is 245 -// Serial1 on Teensy 3.2 @ 96 MHz minimum baud is 733 - -// This example code is in the public domain. - -byte sentbyte; -unsigned long prevmillis; -byte testbyte=0xF0; - -void setup() -{ - delay(200); - Serial.begin(9600); - while (!Serial) ; // wait for Arduino Serial Monitor - Serial1.begin(mybaud); // connect a wire from TX1 - altser.begin(mybaud); // to AltSoftSerial RX - Serial.println("AltSoftSerial Receive Test"); - prevmillis = millis(); -} - -void loop() -{ - // transmit a test byte on Serial 1 - if (millis() - prevmillis > 250) { - sentbyte = testbyte++; - Serial1.write(sentbyte); - prevmillis = millis(); - } - // attempt to receive it by AltSoftSerial - if (altser.available() > 0) { - byte b = altser.read(); - Serial.println(b); - if (b != sentbyte) { - Serial.println("***** ERROR *****"); - } - } -} diff --git a/lib/MySensors/drivers/AltSoftSerial/examples/ShowConfiguration/ShowConfiguration.ino b/lib/MySensors/drivers/AltSoftSerial/examples/ShowConfiguration/ShowConfiguration.ino deleted file mode 100644 index df0b76ed..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/examples/ShowConfiguration/ShowConfiguration.ino +++ /dev/null @@ -1,97 +0,0 @@ -#include - -// AltSoftSerial show configuration example -// Will print library configuration to default serial port -// Open your serial monitor to see config for your board -// Printout would repeat every 10sec (just in case you missed it somehow) - -// Print Configuration -// ----------------------- - -// Direct include AltSoftSerial internals to obtaion PIN setup (you do not need this in regular code) - -// This example code is in the public domain. - -#include - -void printAltSoftSerialSetup(Stream &port) -{ -#define PRINT_PFX "AltSoftSerial:" -#define PRINT_PIN_NAME(pin,name) { char buffer[128+1]; sprintf(buffer, PRINT_PFX "PIN:%2d %s", (int)pin, (const char*)name); port.println(buffer); } - - port.println(PRINT_PFX "Setup info: begin"); - -#if defined(ALTSS_USE_FTM0) - port.println(PRINT_PFX "USE FTM0"); -#endif - -#if defined(ALTSS_USE_TIMER1) - port.println(PRINT_PFX "USE TIMER1"); -#endif - -#if defined(ALTSS_USE_TIMER2) - port.println(PRINT_PFX "USE TIMER2"); -#endif - -#if defined(ALTSS_USE_TIMER3) - port.println(PRINT_PFX "USE TIMER3"); -#endif - -#if defined(ALTSS_USE_TIMER4) - port.println(PRINT_PFX "USE TIMER4"); -#endif - -#if defined(ALTSS_USE_TIMER5) - port.println(PRINT_PFX "USE TIMER5"); -#endif - -#if defined(INPUT_CAPTURE_PIN) - PRINT_PIN_NAME(INPUT_CAPTURE_PIN,"RX"); -#endif - -#if defined(OUTPUT_COMPARE_A_PIN) - PRINT_PIN_NAME(OUTPUT_COMPARE_A_PIN,"TX"); -#endif - -#if defined(OUTPUT_COMPARE_B_PIN) - PRINT_PIN_NAME(OUTPUT_COMPARE_B_PIN,"(unused PWM)"); -#endif - -#if defined(OUTPUT_COMPARE_C_PIN) - PRINT_PIN_NAME(OUTPUT_COMPARE_C_PIN,"(unused PWM)"); -#endif - -#if defined(OUTPUT_COMPARE_D_PIN) - PRINT_PIN_NAME(OUTPUT_COMPARE_D_PIN,"(unused PWM)"); -#endif - -#if defined(OUTPUT_COMPARE_E_PIN) - PRINT_PIN_NAME(OUTPUT_COMPARE_E_PIN,"(unused PWM)"); -#endif - -#if defined(OUTPUT_COMPARE_F_PIN) - PRINT_PIN_NAME(OUTPUT_COMPARE_F_PIN,"(unused PWM)"); -#endif - - port.println(PRINT_PFX "Setup info: end"); - -#undef PRINT_PIN_NAME -#undef PRINT_PFX -} - -void setup() -{ - // Open default serial to dump config to - Serial.begin(9600); - while (!Serial) ; // wait for serial monitor - printAltSoftSerialSetup(Serial); -} - -void loop() -{ - // Repeat every 10 sec (just in case) - delay(10000); - Serial.println(""); - printAltSoftSerialSetup(Serial); -} - diff --git a/lib/MySensors/drivers/AltSoftSerial/keywords.txt b/lib/MySensors/drivers/AltSoftSerial/keywords.txt deleted file mode 100644 index f2bf10db..00000000 --- a/lib/MySensors/drivers/AltSoftSerial/keywords.txt +++ /dev/null @@ -1,4 +0,0 @@ -AltSoftSerial KEYWORD1 -active KEYWORD2 -overflow KEYWORD2 -library_version KEYWORD2 diff --git a/lib/MySensors/drivers/CircularBuffer/CircularBuffer.h b/lib/MySensors/drivers/CircularBuffer/CircularBuffer.h deleted file mode 100644 index 0f03b490..00000000 --- a/lib/MySensors/drivers/CircularBuffer/CircularBuffer.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - CircularBuffer - An Arduino circular buffering library for arbitrary types. - - Created by Ivo Pullens, Emmission, 2014-2016 -- www.emmission.nl - - 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 -*/ - -/** -* @file CircularBuffer.h -* -* Circular buffering for arbitrary types. -*/ - -#ifndef CircularBuffer_h -#define CircularBuffer_h - -/** - * The circular buffer class. - * Pass the datatype to be stored in the buffer as template parameter. - */ -template class CircularBuffer -{ -public: - /** - * Constructor - * @param buffer Preallocated buffer of at least size records. - * @param size Number of records available in the buffer. - */ - CircularBuffer(T* buffer, const uint8_t size ) - : m_size(size), m_buff(buffer) - { - clear(); - } - - /** - * Clear all entries in the circular buffer. - */ - void clear(void) - { - MY_CRITICAL_SECTION { - m_front = 0; - m_fill = 0; - } - } - - /** - * Test if the circular buffer is empty. - * @return True, when empty. - */ - inline bool empty(void) const - { - bool empty; - MY_CRITICAL_SECTION { - empty = !m_fill; - } - return empty; - } - - /** - * Test if the circular buffer is full. - * @return True, when full. - */ - inline bool full(void) const - { - bool full; - MY_CRITICAL_SECTION { - full = m_fill == m_size; - } - return full; - } - - /** - * Return the number of records stored in the buffer. - * @return number of records. - */ - inline uint8_t available(void) const - { - uint8_t ret_value; - MY_CRITICAL_SECTION { - ret_value = m_fill; - } - return ret_value; - } - - /** - * Aquire unused record on front of the buffer, for writing. - * After filling the record, it has to be pushed to actually - * add it to the buffer. - * @return Pointer to record, or NULL when buffer is full. - */ - T* getFront(void) const - { - MY_CRITICAL_SECTION { - if (!full()) - { - return get(m_front); - } - } - return static_cast(NULL); - } - - /** - * Push record to front of the buffer. - * @param record Record to push. If record was aquired previously (using getFront) its - * data will not be copied as it is already present in the buffer. - * @return True, when record was pushed successfully. - */ - bool pushFront(T* record) - { - MY_CRITICAL_SECTION { - if (!full()) - { - T* f = get(m_front); - if (f != record) { - *f = *record; - } - m_front = (m_front+1) % m_size; - m_fill++; - return true; - } - } - return false; - } - - /** - * Aquire record on back of the buffer, for reading. - * After reading the record, it has to be pop'ed to actually - * remove it from the buffer. - * @return Pointer to record, or NULL when buffer is empty. - */ - T* getBack(void) const - { - MY_CRITICAL_SECTION { - if (!empty()) - { - return get(back()); - } - } - return static_cast(NULL); - } - - /** - * Remove record from back of the buffer. - * @return True, when record was pop'ed successfully. - */ - bool popBack(void) - { - MY_CRITICAL_SECTION { - if (!empty()) - { - m_fill--; - return true; - } - } - return false; - } - -protected: - /** - * Internal getter for records. - * @param idx Record index in buffer. - * @return Ptr to record. - */ - inline T * get(const uint8_t idx) const - { - return &(m_buff[idx]); - } - - /** - * Internal getter for index of last used record in buffer. - * @return Index of last record. - */ - inline uint8_t back(void) const - { - return (m_front - m_fill + m_size) % m_size; - } - - const uint8_t m_size; //!< Total number of records that can be stored in the buffer. - T* const m_buff; //!< Ptr to buffer holding all records. - volatile uint8_t m_front; //!< Index of front element (not pushed yet). - volatile uint8_t m_fill; //!< Amount of records currently pushed. -}; - -#endif // CircularBuffer_h diff --git a/lib/MySensors/drivers/I2CEeprom/I2CEeprom.cpp b/lib/MySensors/drivers/I2CEeprom/I2CEeprom.cpp deleted file mode 100644 index a54dfc8f..00000000 --- a/lib/MySensors/drivers/I2CEeprom/I2CEeprom.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2016 Krister W. -// -// Original SPI flash driver this is based on: -// Copyright (c) 2013-2015 by Felix Rusu, LowPowerLab.com -// ********************************************************************************** -// License -// ********************************************************************************** -// 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 . -// -// Licence can be viewed at -// http://www.gnu.org/licenses/gpl-3.0.txt -// -// Please maintain this license information along with authorship -// and copyright notices in any redistribution of this code - -#include -#include "I2CEeprom.h" - -I2CEeprom::I2CEeprom(uint8_t addr) : extEEPROM(I2CEEPROM_CHIP_SIZE, 1, I2CEEPROM_PAGE_SIZE) -{ - m_addr = addr; // we only need this for busy() -} - -/// setup -bool I2CEeprom::initialize() -{ - return extEEPROM::begin(I2CEEPROM_TWI_CLK) ? false : true; -} - -/// read 1 byte -uint8_t I2CEeprom::readByte(uint32_t addr) -{ - uint8_t val; - readBytes(addr, &val, 1); - return val; -} - -/// read multiple bytes -void I2CEeprom::readBytes(uint32_t addr, void* buf, uint16_t len) -{ - extEEPROM::read((unsigned long)addr, (byte *)buf, (unsigned int) len); -} - -/// check if the chip is busy -bool I2CEeprom::busy() -{ - Wire.beginTransmission(m_addr); - Wire.write(0); - Wire.write(0); - if (Wire.endTransmission() == 0) { - return false; - } else { - return true; // busy - } -} - -/// Write 1 byte -void I2CEeprom::writeByte(uint32_t addr, uint8_t byt) -{ - writeBytes(addr, &byt, 1); -} - -/// write multiple bytes -void I2CEeprom::writeBytes(uint32_t addr, const void* buf, uint16_t len) -{ - extEEPROM::write((unsigned long) addr, (byte *)buf, (unsigned int) len); -} diff --git a/lib/MySensors/drivers/I2CEeprom/I2CEeprom.h b/lib/MySensors/drivers/I2CEeprom/I2CEeprom.h deleted file mode 100644 index 96934c5b..00000000 --- a/lib/MySensors/drivers/I2CEeprom/I2CEeprom.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) 2016 Krister W. -// -// Original SPI flash driver this is based on: -// Copyright (c) 2013-2015 by Felix Rusu, LowPowerLab.com -// -// I2C EEPROM library for MySensors OTA. Based on SPI Flash memory library for -// arduino/moteino. -// This driver is made to look like the SPI flash driver so changes needed to -// MySensors OTA code is minimized. -// This works with 32 or 64kB I2C EEPROM like an 24(L)C256. AVR HW I2C is assumed -// and error handling is quite minimal. Uses extEEPROM as the underlying driver. -// DEPENDS ON: Arduino Wire library, extEEPROM -// ********************************************************************************** -// License -// ********************************************************************************** -// 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 . -// -// Licence can be viewed at -// http://www.gnu.org/licenses/gpl-3.0.txt -// -// Please maintain this license information along with authorship -// and copyright notices in any redistribution of this code - -/// -/// @file I2CEeprom.h -/// -/// @brief I2CEeprom provides access to a I2C EEPROM IC for OTA update or storing data -/// -/// This is a wrapper over extEEPROM to make it look like a flash chip. -/// -#ifndef _I2CEeprom_H_ -#define _I2CEeprom_H_ - -#include -#include - -/// I2C speed -// 400kHz clock as default. Use extEEPROM type -#ifndef I2CEEPROM_TWI_CLK -#define I2CEEPROM_TWI_CLK twiClock400kHz -#endif - -/// EEPROM page size -//Typically 64 (see data sheet for your EEPROM) -// Some 512kbit chips use 128 byte pages (e.g. Atmel AT24C512) -#ifndef I2CEEPROM_PAGE_SIZE -#define I2CEEPROM_PAGE_SIZE 64 -#endif - -/// EEPROM size -// 24C256 is 32kB, minimum that fits code for ATmega328 -// Use extEEPROM type -#ifndef I2CEEPROM_CHIP_SIZE -#define I2CEEPROM_CHIP_SIZE kbits_256 -#endif - -/** I2CEeprom class */ -class I2CEeprom : extEEPROM -{ -public: - - explicit I2CEeprom(uint8_t addr); //!< Constructor - bool initialize(); //!< setup - uint8_t readByte(uint32_t addr); //!< read 1 byte from flash memory - void readBytes(uint32_t addr, void* buf, uint16_t len); //!< read multiple bytes - void writeByte(uint32_t addr, uint8_t byt); //!< Write 1 byte to flash memory - void writeBytes(uint32_t addr, const void* buf, - uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used - bool busy(); //!< check if the chip is busy erasing/writing - - // the rest not needed for EEPROMs, but kept so SPI flash code compiles as is (functions are NOP) - - /// dummy function for SPI flash compatibility - uint16_t readDeviceId() - { - return 0xDEAD; - }; - /// dummy function for SPI flash compatibility - void chipErase() {}; - /// dummy function for SPI flash compatibility - void blockErase4K(uint32_t address) - { - (void)address; - }; - /// dummy function for SPI flash compatibility - void blockErase32K(uint32_t address) - { - (void)address; - }; - /// dummy function for SPI flash compatibility - void sleep() {}; - /// dummy function for SPI flash compatibility - void wakeup() {}; - /// dummy function for SPI flash compatibility - void end() {}; - -protected: - - uint8_t m_addr; ///< I2C address for busy() -}; - -#endif diff --git a/lib/MySensors/drivers/NVM/Flash.h b/lib/MySensors/drivers/NVM/Flash.h deleted file mode 100644 index de23b7e3..00000000 --- a/lib/MySensors/drivers/NVM/Flash.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Flash.h - Flash library - * Original Copyright (c) 2017 Frank Holtz. All right reserved. - * - * 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 - */ -/** - * @file Flash.h - * @brief Flash abstraction layer - * - * @ingroup NVM - * @details Nonvolatile Memory Class - * @{ - */ - -#pragma once - -#include -#include // for size_t - -/* - * Define characteristics of Flash - * - * @def FLASH_ERASE_CYCLES - * @brief Specified number of erase cycles - * - * @def FLASH_PAGE_SIZE - * @brief Used/supported Flash page size - * - * @def FLASH_ERASE_PAGE_TIME - * @brief Time in ms to delete a page - * - * @def FLASH_WRITES_PER_WORD - * @brief How often a dataword (32 bit) can be written - * - * @def FLASH_WRITES_PER_PAGE - * @brief How many writes are allowed into a page - * - * @def FLASH_SUPPORTS_RANDOM_WRITE - * @brief Set this if it is allowed to write to a page in random order. - */ - -#if defined(NRF51) -#define FLASH_ERASE_CYCLES 20000 -#define FLASH_PAGE_SIZE 1024 -#define FLASH_ERASE_PAGE_TIME 23 -#define FLASH_SUPPORTS_RANDOM_WRITE true -#define FLASH_WRITES_PER_WORD 2 -#define FLASH_WRITES_PER_PAGE 512 -#elif defined(NRF52) -#define FLASH_ERASE_CYCLES 10000 -#define FLASH_PAGE_SIZE 4096 -#define FLASH_ERASE_PAGE_TIME 90 -#define FLASH_SUPPORTS_RANDOM_WRITE true -#define FLASH_WRITES_PER_WORD 32 -#define FLASH_WRITES_PER_PAGE 181 -#elif defined(NRF52840) -#define FLASH_ERASE_CYCLES 10000 -#define FLASH_PAGE_SIZE 4096 -#define FLASH_ERASE_PAGE_TIME 90 -#define FLASH_SUPPORTS_RANDOM_WRITE true -#define FLASH_WRITES_PER_WORD 2 -#define FLASH_WRITES_PER_PAGE 403 -#else -#define FLASH_ERASE_CYCLES 10000 //!< FLASH_ERASE_CYCLES -#define FLASH_PAGE_SIZE 4096 //!< FLASH_PAGE_SIZE -#define FLASH_ERASE_PAGE_TIME 100 //!< FLASH_ERASE_PAGE_TIME -//#define FLASH_SUPPORTS_RANDOM_WRITE true -#define FLASH_WRITES_PER_WORD 1 //!< FLASH_WRITES_PER_WORD -#warning "Unknown platform. Please check the code." -#endif - -/** - * @class FlashClass - * @brief This class provides low-level access to internal Flash memory. - */ -class FlashClass -{ -public: - //---------------------------------------------------------------------------- - /** Constructor */ - FlashClass() {}; - //---------------------------------------------------------------------------- - /** Initialize Flash */ - void begin() {}; - /** Deinitialize Flash */ - void end() {}; - //---------------------------------------------------------------------------- - /* - * Physical flash geometry - */ - //---------------------------------------------------------------------------- - /** Page size in bytes - * @return Number of bytes - */ - uint32_t page_size() const; - //---------------------------------------------------------------------------- - /** Page address width in bits. Page size is 2^x - * @return Number of bits - */ - uint8_t page_size_bits() const; - //---------------------------------------------------------------------------- - /** Number of managed flash pages - * @return Number of pages - */ - uint32_t page_count() const; - //---------------------------------------------------------------------------- - /** Number of page erase cycles - * @return Number of page erase cycles - */ - uint32_t specified_erase_cycles() const; - //---------------------------------------------------------------------------- - /** Get a address of a page - * @param[in] page Page number, starting at 0 - * @return address of given page - */ - uint32_t *page_address(size_t page); - /** Get top of available flash for application data - * @return Last available address + 1 - */ - uint32_t *top_app_page_address(); - //---------------------------------------------------------------------------- - /* - * Accessing flash memory - */ - //---------------------------------------------------------------------------- - /** Erase a page of given size. Size must be page_size aligned! - * Take care about RADIO, WDT and Interrupt timing! - * @param[in] *address Pointer to page - * @param[in] size number of page aligned bytes to erase - */ - void erase(uint32_t *address, size_t size); - //---------------------------------------------------------------------------- - /** Erase the complete MCU. This can brick your device! - */ - void erase_all(); - //---------------------------------------------------------------------------- - /** write a aligned 32 bit word to flash. - * @param[in] *address 32 bit aligned pointer to destination word - * @param[in] value Data word to write - */ - void write(uint32_t *address, uint32_t value); - //---------------------------------------------------------------------------- - /** write a aligned block to flash. - * @param[in] *dst_address 32 bit aligned pointer to destination - * @param[in] *src_address 32 bit aligned pointer to source - * @param[in] word_count Number of words to write - */ - void write_block(uint32_t *dst_address, uint32_t *src_address, - uint16_t word_count); - -private: - // Wait until flash is ready - void wait_for_ready(); -}; - -extern FlashClass Flash; //!< extern FlashClass - -/** Load Hardwarespecific files */ -#ifdef NRF5 -#include "hal/architecture/NRF5/drivers/Flash.cpp" -#else -#error "Unsupported platform." -#endif - -/** @} */ diff --git a/lib/MySensors/drivers/NVM/NVRAM.cpp b/lib/MySensors/drivers/NVM/NVRAM.cpp deleted file mode 100644 index 9117ba61..00000000 --- a/lib/MySensors/drivers/NVM/NVRAM.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* - NVRAM.cpp - Byte wise storage for Virtual Pages. - Original Copyright (c) 2017 Frank Holtz. All right reserved. - - 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 "NVRAM.h" - -// VirtualPage magic -#define NVRAM_MAGIC (0x7710fdb9) -// Number of emulated cells -#define NVRAM_LENGTH 3072 -// Log configuration: Address index in bits -#define NVRAM_ADDR_POS 20 -// Log configuration: Mask for comparsion (4k space) -#define NVRAM_ADDR_MASK 0xfff00000 -// Log configuration: Bit position of used address bitmap -#define NVRAM_BITMAP_POS 8 -// Log configuration: used address bitmap calulation -#define NVRAM_BITMAP_ADDR_SHIFT 8 -// Log configuration: Mask for bitmap extraction -#define NVRAM_BITMAP_MASK 0x000fff00 -#define ADDR2BIT(index) \ - ((1 << (index >> NVRAM_BITMAP_ADDR_SHIFT)) << NVRAM_BITMAP_POS) - -NVRAMClass NVRAM; - -uint16_t NVRAMClass::length() const -{ - return (NVRAM_LENGTH); -} - -void NVRAMClass::read_block(uint8_t *dst, uint16_t idx, uint16_t n) -{ - uint32_t *vpage; - uint16_t log_start, log_end; - - // find correct page - vpage = get_page(); - - // copy 0xff to dst when no page is available - if (vpage == (uint32_t *)~0) { - for (uint32_t i = 0; i < n; i++) { - ((uint8_t *)dst)[i] = 0xff; - } - return; - } - - // calculate actual log position - log_end = get_log_position(vpage); - if (log_end == 0) { - log_start = 1; - } else { - log_start = vpage[0] + 1; - } - /* - Serial.print("\r\nread_block idx="); - Serial.print(idx); - Serial.print(" n="); - Serial.print(n); - Serial.print("("); */ - while (n > 0) { - // Read cell - *dst = get_byte_from_page(vpage, log_start, log_end, idx); - // Serial.print(*dst, HEX); - // calculate next address - n--; - dst++; - idx++; - } - // Serial.println(")"); -} - -uint8_t NVRAMClass::read(const uint16_t idx) -{ - uint8_t ret; - read_block(&ret, idx, 1); - return ret; -} - -bool NVRAMClass::write_block(uint8_t *src, uint16_t idx, uint16_t n) -{ - uint32_t *vpage; - uint32_t bitmap; - uint16_t log_start, log_end; - - // find correct page - vpage = get_page(); - - // return on invalid page - if (vpage == (uint32_t *)~0) { - return false; - } - - // calculate actual log position - log_start = vpage[0] + 1; - log_end = get_log_position(vpage); - if (log_end > log_start) { - bitmap = vpage[log_end - 1] & NVRAM_BITMAP_MASK; - } else { - bitmap = 0; - } - - while (n > 0) { - // Read cell - uint8_t old_value = get_byte_from_page(vpage, log_start, log_end, idx); - uint8_t new_value = *src; - - // Have to write into log? - if (new_value != old_value) { - - // need to calculate a new page? - if (log_end >= VirtualPage.length()) { - vpage = switch_page(vpage, &log_start, &log_end); - if (vpage == (uint32_t *)~0) { - // do nothing if no page is available - return false; - } - bitmap = 0; - } - - // Add Entry into log - Flash.write(&vpage[log_end], (idx << NVRAM_ADDR_POS) | bitmap | - ADDR2BIT(idx) | (uint32_t)new_value); - log_end++; - } - - // calculate next address - n--; - src++; - idx++; - } - return true; -} - -bool NVRAMClass::write(uint16_t idx, uint8_t value) -{ - return (write_block(&value, idx, 1)); -} - -int NVRAMClass::write_prepare(uint16_t number) -{ - // find correct page - uint32_t *vpage = get_page(); - // Want to write to much or into an invalid page? - if ((vpage == (uint32_t *)~0) || (number > length())) { - return -1; - } - - // calculate actual log position - uint16_t log_end = get_log_position(vpage); - - // Calculate number of free bytes in log - int free_bytes = ((VirtualPage.length() - 1) - log_end); - - // switch page when - if (free_bytes < number) { - uint16_t log_start = vpage[0] + 1; - vpage = switch_page(vpage, &log_start, &log_end); - if (vpage == (uint32_t *)~0) { - // do nothing if no page is available - return -1; - } - log_end = get_log_position(vpage); - free_bytes = ((VirtualPage.length() - 1) - log_end); - } - return free_bytes; -} - -void NVRAMClass::clean_up(uint16_t write_preserve) -{ - VirtualPage.clean_up(); - if (write_preserve > 0) { - write_prepare(write_preserve); - } -} - -uint32_t *NVRAMClass::switch_page(uint32_t *old_vpage, uint16_t *log_start, - uint16_t *log_end) -{ - // Mark old page as in release - VirtualPage.release_prepare(old_vpage); - - // Get a blank page - uint32_t *new_vpage = VirtualPage.allocate(NVRAM_MAGIC, VirtualPage.length()); - if (new_vpage == (uint32_t *)~0) { - // failed - return new_vpage; - } - - // Store four bytes for map creation - uint32_t value; - - // Length of new map - uint16_t map_length = 0; - - // Build map -#ifdef FLASH_SUPPORTS_RANDOM_WRITE - // Copy current values - for (uint16_t i = 0; i < (NVRAM_LENGTH >> 2); i++) { - read_block((uint8_t *)&value, i << 2, 4); - if (value != (uint32_t)~0) { - // Value found - map_length = i + 1; - Flash.write(&new_vpage[i + 1], value); - } - } - // Store map length - Flash.write(new_vpage, map_length); -#else - // find map length - for (uint16_t i = (NVRAM_LENGTH >> 2); i > 0; i--) { - read_block((uint8_t *)&value, i << 2, 4); - if (value != (uint32_t)~0) { - // Value found - map_length = i; - break; - } - } - map_length++; - - // Store map length - Flash.write(new_vpage, map_length); - - // Copy current values - for (uint16_t i = 0; i <= map_length; i++) { - read_block((uint8_t *)&value, i << 2, 4); - if (value != (uint32_t)~0) { - // Value found - map_length = i; - Flash.write(&new_vpage[i + 1], value); - } - } -#endif - - // Release old page - VirtualPage.release(old_vpage); - - // Set log position - *log_start = map_length + 1; - *log_end = *log_start; - - return new_vpage; -} - -uint32_t *NVRAMClass::get_page() -{ - uint32_t *vpage = VirtualPage.get(NVRAM_MAGIC); - // Invalid page? - if (vpage == (uint32_t *)~0) { - // Allocate a new page - vpage = VirtualPage.allocate(NVRAM_MAGIC, VirtualPage.length()); - // Set map length to 0 - Flash.write(&vpage[0], 0x0); - } - return vpage; -} - -uint16_t NVRAMClass::get_log_position(uint32_t *vpage) -{ - uint16_t position_min = vpage[0] + 1; - uint16_t position_max = VirtualPage.length(); - - // Return if page is not filled - if ((vpage[0] == (uint32_t)~0) || (position_min >= position_max)) { - return 0; - } - - // loop until postition_min != position_max-1 - while (position_min != position_max - 1) { - // Calculate middle between min and max - uint16_t mid = position_min + ((position_max - position_min) >> 1); - // Set max or min to current position - if (vpage[mid] == (uint32_t)~0) { - position_max = mid; - } else { - position_min = mid; - } - } - - return position_max; -} - -uint8_t NVRAMClass::get_byte_from_page(uint32_t *vpage, uint16_t log_start, - uint16_t log_end, uint16_t idx) -{ - // mask matching a bit signaling wich address range is in log - uint32_t address_mask = ADDR2BIT(idx); - // mask matching the index address - uint32_t address_match = idx << NVRAM_ADDR_POS; - - // Check the log backwards - while (log_end > log_start) { - log_end--; - uint32_t value = vpage[log_end]; - // end here if address map bit is not set - if ((value & address_mask) == 0) { - break; - } - // check address match -> update found -> return - if ((value & NVRAM_ADDR_MASK) == address_match) { - return (uint8_t)value; - } - } - - // Calculate address in the eeprom map at the beginning of a vpage - uint16_t map_address = (idx >> 2); - map_address++; // jump over log offset field - - // look at map if calculated addess before log start position - if (map_address < log_start) { - switch (idx % 4) { - case 3: - return (uint8_t)(vpage[map_address] >> 24); - break; - case 2: - return (uint8_t)(vpage[map_address] >> 16); - break; - case 1: - return (uint8_t)(vpage[map_address] >> 8); - break; - default: - return (uint8_t)(vpage[map_address]); - break; - } - } - - // empty cell - return 0xff; -} diff --git a/lib/MySensors/drivers/NVM/NVRAM.h b/lib/MySensors/drivers/NVM/NVRAM.h deleted file mode 100644 index 08c75521..00000000 --- a/lib/MySensors/drivers/NVM/NVRAM.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * NVRAM.h - Byte-wise storage for Virtual Pages. - * Original Copyright (c) 2017 Frank Holtz. All right reserved. - * - * 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 -*/ -/** - * @file NVRAM.h - * @brief Byte-wise storage for Virtual Pages. - * - * @defgroup NVM Nonvolatile Memory - * @ingroup internals - * @details Nonvolatile Memory Class - * @{ - */ -#pragma once - -#include "Flash.h" -#include "VirtualPage.h" -#include - -/** - * @class NVRAMClass - * @brief Nonvolatile Memory - */ -class NVRAMClass -{ -public: - //---------------------------------------------------------------------------- - /** Constructor. */ - NVRAMClass() {}; - //---------------------------------------------------------------------------- - /** Initialize Class */ - void begin() {}; - //---------------------------------------------------------------------------- - /** Deinitialize Class */ - void end() {}; - //---------------------------------------------------------------------------- - /** NVM available space in bytes - * @return Number of bytes - */ - uint16_t length() const; - //---------------------------------------------------------------------------- - /** Read a block of bytes - * @param[in] *dst Write bytes to given pointer - * @param[in] idx First NVM address to read - * @param[in] n Number of bytes to read - */ - void read_block(uint8_t *dst, uint16_t idx, uint16_t n); - //---------------------------------------------------------------------------- - /** Read a byte - * @param[in] idx NVM Address to read - * @return Byte from given address - */ - uint8_t read(const uint16_t idx); - //---------------------------------------------------------------------------- - /** Write a block - * @param[in] *src Read bytes from given pointer - * @param[in] idx First NVM address to write - * @param[in] n Number of bytes to write - * @return success - */ - bool write_block(uint8_t *src, uint16_t idx, uint16_t n); - //---------------------------------------------------------------------------- - /** Write a byte - * @param[in] idx NVM Address to write - * @param[in] value Byte to write - * @return success - */ - bool write(const uint16_t idx, uint8_t value); - //---------------------------------------------------------------------------- - /** Preserve the number of bytes in NVM log for time critical writes. Runtime - * up to 5000ms! - * @param[in] number Bytes to preserve, can 0 to find out free log space - * @return Bytes available for writing - */ - int write_prepare(uint16_t number); - //---------------------------------------------------------------------------- - /** lear log if full and prepare released pages for faster reallocation. - * Runtime up to 5000ms! - * @param[in] write_preserve Byte to preserve - */ - void clean_up(uint16_t write_preserve); - -private: - // Return a virtual page - uint32_t *get_page(); - // Get actual log position - uint16_t get_log_position(uint32_t *vpage); - // Read a byte from page - uint8_t get_byte_from_page(uint32_t *vpage, uint16_t log_start, - uint16_t log_end, uint16_t idx); - // switch a page - uint32_t *switch_page(uint32_t *old_vpage, uint16_t *log_start, - uint16_t *log_end); -}; - -/** Variable to access the NVRAMClass */ -extern NVRAMClass NVRAM; - -/** @} */ diff --git a/lib/MySensors/drivers/NVM/README.md b/lib/MySensors/drivers/NVM/README.md deleted file mode 100644 index 259b93fd..00000000 --- a/lib/MySensors/drivers/NVM/README.md +++ /dev/null @@ -1,51 +0,0 @@ -This code is based on (arduino-NVM)[https://github.com/d00616/arduino-NVM]. If you change code, please create a Pull Request for arduino-NVM to keep code synchronized. - -# arduino-NVM - -[![Build Status](https://travis-ci.org/d00616/arduino-NVM.svg?branch=master)](https://travis-ci.org/d00616/arduino-NVM) - -This library allows the usage of internal Flash memory. To enhance the limited erase cycles a VirtualPage layer is available. On top of VirtualPage, there is an NVRAM class to allow a lot of writes by using a log-based storage. - -For Arduino compatibility, a subset of avr/eeprom.h functionality and a complete port of EEPROM.h is provided. - -Accessing bytes via NVRAM or EEPROM is faster than an AVR controller until the internal log is full. At this point, a new page must build. This process takes up to 3400ms (nRF51) or 1300ms (nRF52) depending on your hardware and the highest written address. - -To find out more about timing, please run "test_all" example. - -_This code is not compatible with any SoftDevice. You have to use the [radio notification](https://devzone.nordicsemi.com/tutorials/14/radio-notification/) and VirtualPage.clean_up()/NVRAM.write_prepare(NUMBER) to ensure that writes are only used in a time without radio activation._ - -## Flash.h - -This class is the hardware abstraction to the Flash controller. Please look into Flash.h for a more detailed description. - -Please read the documentation of your microcontroller to find out limitations about writing into flash. You can use the FLASH_... defines in your code to take care about quirks. - -## VirtualPage.h - -This class provides manages Flash pages. This helps you to reach more erase cycles and handle page faults. The underlying Flash page needs to hold some metadata so a VirtualPage is some bytes smaller than 4k. The size can differ between different hardware. - -If you need to allocate VirtualPages in performance critical situations, call VirtualPage.clean_up(), when you have a time slot of more than 100ms. - -For VirtualPages the last 16k(nRF51) or 32k(nRF52) are used. This allows the same number of erase cycles on both platforms. - -## NVRAM.h - -This class provides a 3072 bytes large memory. You can access this memory in a random order without needing to take care of the underlying flash architecture. This class is stateless, this means there is nothing cached in RAM. With every access, the data structure is parsed. This saves RAM and avoids conflicts when you have more than one instance of NVRAM class in your code. - -To reach a maximum of write cycles and performance, place all your data at the beginning of the memory. This allows a maximum of write cycles. - -When you only use the first 8 Bytes of the NVRAM, you have 5,100,000 write cycles per byte. If you use all 3072 bytes, you have only 3,300 write cycles per byte. - -For your own calculation of write cycles, you can calculate the sum of available writes with: (VirtualPage.length()-4-HIGHEST_ADDRESS/4)*40,000 - -Reading or writing the NVRAM is fast until the internal log is full. On nRF51 you can calculate with 1.2ms and on nRF52 with 0,5ms. If the log is full a new VirtualPage is allocated and written. This procedure can take a time of 3400ms (nRF51) or 1300ms (nRF52). - -If you use this code in performance critical situations. Use NVRAM.write_prepare(NUMBER) before to guarantee a fast write for the given number of bytes. - -## EEPROM.h and avr_eeprom.h - -Both libraries are for Arduino compatibility. Instead of avr/eeprom.h, you have to include avr_eeprom.h. This file maps a limited set of functions to NVRAM. - -The EEPROM.h is fully compatible with the AVR version without committing changes. - -If you use one of both files, please keep in mind that writing a single byte is fast until the log becomes full. In that case, a single write operation can take up to 3400ms (nRF51) or 1300ms (nRF52). diff --git a/lib/MySensors/drivers/NVM/VirtualPage.cpp b/lib/MySensors/drivers/NVM/VirtualPage.cpp deleted file mode 100644 index 6eaeb7e3..00000000 --- a/lib/MySensors/drivers/NVM/VirtualPage.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* - VirtualPage.cpp - Flash page management - Original Copyright (c) 2017 Frank Holtz. All right reserved. - - 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 "VirtualPage.h" - -VirtualPageClass VirtualPage; - -#ifndef NVM_VIRTUAL_PAGE_SIZE_BITS -#define NVM_VIRTUAL_PAGE_SIZE_BITS 12 -#elif NVM_VIRTUAL_PAGE_SIZE_BITS < 12 -#error "NVM_VIRTUAL_PAGE_SIZE_BITS must be >= 12" -#endif - -// Calculate virtual page count, when mcuboot is present -#if defined(MCUBOOT_PRESENT) && !defined(NVM_VIRTUAL_PAGE_COUNT) -// mcuboot zephyr build via generated_dts_board.h -#include "generated_dts_board.h" -// Calculate number of free pages after scratch area -#define NVM_VIRTUAL_PAGE_COUNT (((CONFIG_FLASH_SIZE_0<<10)-(FLASH_AREA_IMAGE_SCRATCH_OFFSET_0+FLASH_AREA_IMAGE_SCRATCH_SIZE_0)) >> NVM_VIRTUAL_PAGE_SIZE_BITS) -#endif - -// check page size -#ifndef NVM_VIRTUAL_PAGE_COUNT -#if FLASH_ERASE_CYCLES >= 20000 -// use 16k of flash memory -#define NVM_VIRTUAL_PAGE_COUNT 4 -#else -// use 32k of flash memory -#define NVM_VIRTUAL_PAGE_COUNT 8 -#endif -#endif - -/* - * How many virtual pages are skipped from top of flash - */ -#ifndef NVM_VIRTUAL_PAGE_SKIP_FROM_TOP -#define NVM_VIRTUAL_PAGE_SKIP_FROM_TOP 0 -#endif - -/* - * Calculate things around NVM_VIRTUAL_PAGE_SIZE - */ -#define NVM_VIRTUAL_PAGE_SIZE (1 << (NVM_VIRTUAL_PAGE_SIZE_BITS)) -#define NVM_VIRTUAL_PAGE_ADDRESS_MASK (~(NVM_VIRTUAL_PAGE_SIZE - 1)) -#define NVM_VIRTUAL_PAGE_ALIGN(address) \ - { address = (uint32_t *)((uint32_t)address & NVM_VIRTUAL_PAGE_ADDRESS_MASK); } - -/* - * Defines the position of status words in a page. - * Offsets are defined in words! - */ -#ifdef FLASH_SUPPORTS_RANDOM_WRITE -// use first 8 byte for magic, erase counter and status -#define OFFSET_MAGIC 0 -#define OFFSET_ERASE_COUNTER 1 -#if FLASH_WRITES_PER_WORD > 2 -// use first 12 bytes for magic, erase counter and status -#define MASK_ERASE_COUNTER 0x00FFFFFF -#define OFFSET_STATUS_RELEASE_PREPARE 1 -#define OFFSET_STATUS_RELEASE_END 1 -#define METADATA_SIZE 8 -#define OFFSET_DATA 2 -#elif FLASH_WRITES_PER_WORD == 2 -#define MASK_ERASE_COUNTER 0x00FFFFFF -#define OFFSET_STATUS_RELEASE_PREPARE 2 -#define OFFSET_STATUS_RELEASE_END 2 -#define METADATA_SIZE 12 -#define OFFSET_DATA 3 -#else -// use first 12 bytes for erase counter, and magic -#define OFFSET_MAGIC 1 -#define OFFSET_COUNTER 0 -#define MASK_ERASE_COUNTER 0x00FFFFFF -#define OFFSET_STATUS_RELEASE_PREPARE NVM_VIRTUAL_PAGE_SIZE - 8 -#define OFFSET_STATUS_RELEASE_END NVM_VIRTUAL_PAGE_SIZE - 4 -#define METADATA_SIZE 16 -#define OFFSET_DATA 4 -#endif - -#define BIT_STATUS_RELEASE_PREPARE (1 << 30) -#define BIT_STATUS_RELEASE_END (1 << 31) - -#define NVM_VIRTUAL_PAGE_DATA_SIZE (NVM_VIRTUAL_PAGE_SIZE - METADATA_SIZE) -#else -// use first 8 byte for magic and erase counter and last 8 byte for page release -#define OFFSET_MAGIC 1 -#define OFFSET_ERASE_COUNTER 0 -#define OFFSET_DATA 2 -#define OFFSET_STATUS_RELEASE_PREPARE \ - ((NVM_VIRTUAL_PAGE_SIZE - 8) / sizeof(uint32_t)) -#define OFFSET_STATUS_RELEASE_END \ - ((NVM_VIRTUAL_PAGE_SIZE - 4) / sizeof(uint32_t)) - -#define MASK_ERASE_COUNTER 0xFFFFFFFF - -#define BIT_STATUS_RELEASE_PREPARE 1 -#define BIT_STATUS_RELEASE_END 1 - -#define NVM_VIRTUAL_PAGE_DATA_SIZE (NVM_VIRTUAL_PAGE_SIZE - 16) - -#endif - -uint16_t VirtualPageClass::size() const -{ - return (NVM_VIRTUAL_PAGE_DATA_SIZE); -} - -uint16_t VirtualPageClass::length() const -{ - return (NVM_VIRTUAL_PAGE_DATA_SIZE / 4); -} - -uint16_t VirtualPageClass::page_count() const -{ - return (NVM_VIRTUAL_PAGE_COUNT - 1); -} - -uint32_t VirtualPageClass::wear_level() -{ - uint32_t max_erase_cycles = 0; - for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { - uint32_t erase_cycles = get_page_erase_cycles(get_page_address(i)); - if (erase_cycles > max_erase_cycles) { - max_erase_cycles = erase_cycles; - } - } - return (uint32_t)((((uint64_t)max_erase_cycles * 10000)) / - Flash.specified_erase_cycles()); -} - -uint32_t *VirtualPageClass::get(uint32_t magic) -{ - - // Give back a page prepared for release and not closed - for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { - uint32_t *page = get_page_address(i); - if ( - // correct magic is set - (page[OFFSET_MAGIC] == magic) && - // page is in release_prepare mode - ((page[OFFSET_STATUS_RELEASE_PREPARE] & BIT_STATUS_RELEASE_PREPARE) == - 0) && - // page is not released - ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) > 0)) { - // Return page in release process with priority - return &page[OFFSET_DATA]; - } - } - - // check if a unreleased page is available - for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { - uint32_t *page = get_page_address(i); - if ( - // correct magic is set - (page[OFFSET_MAGIC] == magic) && - // page is not released - ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) > 0)) { - // return page in normal operation - return &page[OFFSET_DATA]; - } - } - - return (uint32_t *)(~0); -} - -uint32_t *VirtualPageClass::allocate(uint32_t magic) -{ - uint32_t *return_page = (uint32_t *)(~0); - uint32_t max_erase_cycles = (uint32_t)~0; - - // Avoid duplicate allocation of pages, look for the less used page - for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { - uint32_t *page = get_page_address(i); - - // Delete duplicated pages - if ( - // same magic - (page[OFFSET_MAGIC] == magic) && - // Not in release_end state - ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) > 0) && - // Not in release_prepare state - (!release_started(page))) { - // clear the page - build_page(page, (uint32_t)~0); - } - - uint32_t erase_cycles = get_page_erase_cycles(page); - // When the page has less erase cycles and is not marked as failed - if ((erase_cycles < max_erase_cycles) && (page[OFFSET_MAGIC] > 0) && - ( - // magic is empty - (page[OFFSET_MAGIC] == (uint32_t)~0) || - // marked as released - ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) == - 0))) { - max_erase_cycles = erase_cycles; - return_page = page; - } - } - - // return if no page was found - if (return_page == (uint32_t *)~0) { - return return_page; - } - - build_page(return_page, magic); - return &return_page[OFFSET_DATA]; -} - -uint32_t *VirtualPageClass::allocate(uint32_t magic, uint32_t max_writes) -{ - // max_writes is not implemented yet -> page is erased with every allocate - (void)max_writes; - return allocate(magic); -} - -void VirtualPageClass::release_prepare(uint32_t *address) -{ - // move pointer to beginning of the page - NVM_VIRTUAL_PAGE_ALIGN(address); - - // Nothing to do at a empty page - if (address[OFFSET_MAGIC] == (uint32_t)~0) { - return; - } - - if (release_started(address) == false) { - // Clear bit BIT_PAGE_RELEASED - Flash.write(&address[OFFSET_STATUS_RELEASE_PREPARE], - address[OFFSET_STATUS_RELEASE_PREPARE] & - ~BIT_STATUS_RELEASE_PREPARE); - } - return; -} - -void VirtualPageClass::release(uint32_t *address) -{ - // move pointer to beginning of the page - NVM_VIRTUAL_PAGE_ALIGN(address); - - // Nothing to do at a empty page - if (address[OFFSET_MAGIC] == (uint32_t)~0) { - return; - } - - // Check if status bit already cleared - if ((address[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) > 0) { - // Clear bit BIT_PAGE_RELEASED - Flash.write(&address[OFFSET_STATUS_RELEASE_END], - address[OFFSET_STATUS_RELEASE_END] & ~BIT_STATUS_RELEASE_END); - } - return; -} - -bool VirtualPageClass::release_started(uint32_t *address) -{ - // move pointer to beginning of the page - NVM_VIRTUAL_PAGE_ALIGN(address); - - return (address[OFFSET_STATUS_RELEASE_PREPARE] & - BIT_STATUS_RELEASE_PREPARE) == 0; -} - -void VirtualPageClass::fail(uint32_t *address) -{ - // move pointer to beginning of the page - NVM_VIRTUAL_PAGE_ALIGN(address); - - build_page(address, 0x00000000); - return; -} - -void VirtualPageClass::clean_up() -{ - // No page found -> try to give back a page prepared for release - for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { - uint32_t *page = get_page_address(i); - if ((page[OFFSET_STATUS_RELEASE_END] & BIT_STATUS_RELEASE_END) == 0) { - build_page(get_page_address(i), ~0); - return; // a maximum of a page is cleaned -> return - } - } -} - -void VirtualPageClass::format() -{ - for (int i = 1; i <= NVM_VIRTUAL_PAGE_COUNT; i++) { - uint32_t *address = get_page_address(i); - build_page(address, (uint32_t)~0); - } -} - -uint32_t *VirtualPageClass::get_page_address(uint16_t page) -{ - return (uint32_t *)(Flash.top_app_page_address() - - ((page + NVM_VIRTUAL_PAGE_SKIP_FROM_TOP) - << NVM_VIRTUAL_PAGE_SIZE_BITS)); -} - -void VirtualPageClass::build_page(uint32_t *address, uint32_t magic) -{ - // move pointer to beginning of the page - NVM_VIRTUAL_PAGE_ALIGN(address); - // get erase counter - uint32_t erase_counter = get_page_erase_cycles(address); - - // Check if a magic is set - if (address[OFFSET_MAGIC] != (uint32_t)~0) { - Flash.erase(address, NVM_VIRTUAL_PAGE_SIZE); - } else { - // check if page is empty - for (int i = OFFSET_DATA; i < (NVM_VIRTUAL_PAGE_SIZE / 4); i++) { - if (address[i] != (uint32_t)~0) { - Flash.erase(address, NVM_VIRTUAL_PAGE_SIZE); - break; - } - } - } - - // write a new page - Flash.write(&address[OFFSET_MAGIC], magic); - if (address[OFFSET_ERASE_COUNTER] == (uint32_t)~0) { - Flash.write(&address[OFFSET_ERASE_COUNTER], - erase_counter | ~MASK_ERASE_COUNTER); - } -} - -uint32_t VirtualPageClass::get_page_erase_cycles(uint32_t *address) -{ - // Return number of cycles - return ((((uint32_t)address[OFFSET_ERASE_COUNTER])+1) & - (uint32_t)MASK_ERASE_COUNTER); -} diff --git a/lib/MySensors/drivers/NVM/VirtualPage.h b/lib/MySensors/drivers/NVM/VirtualPage.h deleted file mode 100644 index dc3016c1..00000000 --- a/lib/MySensors/drivers/NVM/VirtualPage.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - VirtualPage.h - Flash page management - Original Copyright (c) 2017 Frank Holtz. All right reserved. - - 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 -*/ -/** - * @file VirtualPage.h - * @brief Virtual page management on top of Flash - * The managed pages are organized into VirtualPage.size() sized pages. - * Some Bytes of a Flash page are reserved for a magic number and page management. - * - * @ingroup NVM - * @details Nonvolatile Memory Class - * @{ - */ -#pragma once - -#include "Flash.h" -#include - -/** - * @class VirtualPageClass - * @brief Virtual page management on top of Flash - */ -class VirtualPageClass -{ -public: - //---------------------------------------------------------------------------- - /** Constructor */ - VirtualPageClass() {}; - //---------------------------------------------------------------------------- - /** Initialize Virtual Pages */ - void begin() {}; - //---------------------------------------------------------------------------- - /** Deinitilize Virtual Pages */ - void end() {}; - //---------------------------------------------------------------------------- - /** Reports usable page size in bytes - * @return Number of bytes - */ - uint16_t size() const; - //---------------------------------------------------------------------------- - /** Reports usable page size in 32 Bit words - * @return Number of words - */ - uint16_t length() const; - //---------------------------------------------------------------------------- - /** Reports the maximum number of allocatable pages - * @return Number of pages - */ - uint16_t page_count() const; - //---------------------------------------------------------------------------- - /** Calculates the rate of wear in percent*100. - * Values greater than 10000 indicates exceeding the chip specification. - * This value is only valid for controllers, never erased completely. - * @return calculated level - */ - uint32_t wear_level(); - //---------------------------------------------------------------------------- - /** Search for a page by given, unique magic number. - * Returns a pointer to (uint32_t *)~0 if there is no page. Don't write - * to this address. - * @param[in] magic A magic number to identify the page. - * @return Pointer to a page - */ - uint32_t *get(uint32_t magic); - //---------------------------------------------------------------------------- - /** Returns an address to a blank page or (uint32_t *)~0 if no space - * available. Take care about RADIO, WDT and Interrupt timing! Calculate with - * 0-100ms until a page is available. - * @param[in] magic A magic number to identify the page. - * @return Pointer to a page - */ - uint32_t *allocate(uint32_t magic); - //---------------------------------------------------------------------------- - /** Returns an address to a blank page or (uint32_t *)~0 if no space - * available. Take care about RADIO, WDT and Interrupt timing! Calculate with - * 0-100ms until a page is available. - * This function allows using a page multiple times without erasing on some platforms. - * @param[in] magic A magic number to identify the page. - * @param[in] max_writes The number of planned write operations in page lifecycle. - * @return Pointer to a page - */ - uint32_t *allocate(uint32_t magic, uint32_t max_writes); - //---------------------------------------------------------------------------- - /** Start releasing a page. You have to allocate a new one and then release the - * old page. - * @param[in] *address A pointer to the page to release - */ - void release_prepare(uint32_t *address); - //---------------------------------------------------------------------------- - /** End releasing a page. - * @param[in] *address A pointer to the page to release - */ - void release(uint32_t *address); - //---------------------------------------------------------------------------- - /** Returns true if page is in release_prepare state - * @param[in] *address A pointer to a page - * @return Release state - */ - bool release_started(uint32_t *address); - //---------------------------------------------------------------------------- - /** Mark a page as a defect page. - */ - void fail(uint32_t *address); - //---------------------------------------------------------------------------- - /** Prepare released pages for faster reallocation. Plan with 0-100ms. - */ - void clean_up(); - //---------------------------------------------------------------------------- - /** Release all pages - */ - void format(); - -private: - // convert page number 1..max_pages into an address - uint32_t *get_page_address(uint16_t page); - // build a page - void build_page(uint32_t *address, uint32_t magic); - // return number of erase cycles - uint32_t get_page_erase_cycles(uint32_t *address); -}; - -extern VirtualPageClass VirtualPage; //!< extern VirtualPageClass - -/** @} */ diff --git a/lib/MySensors/drivers/PubSubClient/CHANGES.txt b/lib/MySensors/drivers/PubSubClient/CHANGES.txt deleted file mode 100644 index 01a07ae6..00000000 --- a/lib/MySensors/drivers/PubSubClient/CHANGES.txt +++ /dev/null @@ -1,76 +0,0 @@ -2.7 - * Fix remaining-length handling to prevent buffer overrun - * Add large-payload API - beginPublish/write/publish/endPublish - * Add yield call to improve reliability on ESP - * Add Clean Session flag to connect options - * Add ESP32 support for functional callback signature - * Various other fixes - -2.4 - * Add MQTT_SOCKET_TIMEOUT to prevent it blocking indefinitely - whilst waiting for inbound data - * Fixed return code when publishing >256 bytes - -2.3 - * Add publish(topic,payload,retained) function - -2.2 - * Change code layout to match Arduino Library reqs - -2.1 - * Add MAX_TRANSFER_SIZE def to chunk messages if needed - * Reject topic/payloads that exceed MQTT_MAX_PACKET_SIZE - -2.0 - * Add (and default to) MQTT 3.1.1 support - * Fix PROGMEM handling for Intel Galileo/ESP8266 - * Add overloaded constructors for convenience - * Add chainable setters for server/callback/client/stream - * Add state function to return connack return code - -1.9 - * Do not split MQTT packets over multiple calls to _client->write() - * API change: All constructors now require an instance of Client - to be passed in. - * Fixed example to match 1.8 api changes - dpslwk - * Added username/password support - WilHall - * Added publish_P - publishes messages from PROGMEM - jobytaffey - -1.8 - * KeepAlive interval is configurable in PubSubClient.h - * Maximum packet size is configurable in PubSubClient.h - * API change: Return bool rather than int from various functions - * API change: Length parameter in message callback changed - from int to unsigned int - * Various internal tidy-ups around types -1.7 - * Improved keepalive handling - * Updated to the Arduino-1.0 API -1.6 - * Added the ability to publish a retained message - -1.5 - * Added default constructor - * Fixed compile error when used with arduino-0021 or later - -1.4 - * Fixed connection lost handling - -1.3 - * Fixed packet reading bug in PubSubClient.readPacket - -1.2 - * Fixed compile error when used with arduino-0016 or later - - -1.1 - * Reduced size of library - * Added support for Will messages - * Clarified licensing - see LICENSE.txt - - -1.0 - * Only Quality of Service (QOS) 0 messaging is supported - * The maximum message size, including header, is 128 bytes - * The keepalive interval is set to 30 seconds - * No support for Will messages diff --git a/lib/MySensors/drivers/PubSubClient/LICENSE.txt b/lib/MySensors/drivers/PubSubClient/LICENSE.txt deleted file mode 100644 index 217df35c..00000000 --- a/lib/MySensors/drivers/PubSubClient/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008-2015 Nicholas O'Leary - -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. diff --git a/lib/MySensors/drivers/PubSubClient/PubSubClient.cpp b/lib/MySensors/drivers/PubSubClient/PubSubClient.cpp deleted file mode 100644 index 62d6f785..00000000 --- a/lib/MySensors/drivers/PubSubClient/PubSubClient.cpp +++ /dev/null @@ -1,736 +0,0 @@ -/* - PubSubClient.cpp - A simple client for MQTT. - Nick O'Leary - http://knolleary.net -*/ - -#include "PubSubClient.h" -#include "Arduino.h" - -// Suppress uninitialized member variable in all constructors because some memory can be saved with -// on-demand initialization of these members -// cppcheck-suppress uninitMemberVar -PubSubClient::PubSubClient() -{ - this->_state = MQTT_DISCONNECTED; - this->_client = NULL; - this->stream = NULL; - setCallback(NULL); -} -// cppcheck-suppress uninitMemberVar -PubSubClient::PubSubClient(Client& client) -{ - this->_state = MQTT_DISCONNECTED; - setClient(client); - this->stream = NULL; -} -// cppcheck-suppress uninitMemberVar -PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) -{ - this->_state = MQTT_DISCONNECTED; - setServer(addr, port); - setClient(client); - this->stream = NULL; -} -// cppcheck-suppress uninitMemberVar -PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) -{ - this->_state = MQTT_DISCONNECTED; - setServer(addr,port); - setClient(client); - setStream(stream); -} -// cppcheck-suppress uninitMemberVar -// cppcheck-suppress passedByValue -PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) -{ - this->_state = MQTT_DISCONNECTED; - setServer(addr, port); - setCallback(callback); - setClient(client); - this->stream = NULL; -} -// cppcheck-suppress uninitMemberVar -// cppcheck-suppress passedByValue -PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, - Stream& stream) -{ - this->_state = MQTT_DISCONNECTED; - setServer(addr,port); - setCallback(callback); - setClient(client); - setStream(stream); -} -// cppcheck-suppress uninitMemberVar -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) -{ - this->_state = MQTT_DISCONNECTED; - setServer(ip, port); - setClient(client); - this->stream = NULL; -} -// cppcheck-suppress uninitMemberVar -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) -{ - this->_state = MQTT_DISCONNECTED; - setServer(ip,port); - setClient(client); - setStream(stream); -} -// cppcheck-suppress uninitMemberVar -// cppcheck-suppress passedByValue -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) -{ - this->_state = MQTT_DISCONNECTED; - setServer(ip, port); - setCallback(callback); - setClient(client); - this->stream = NULL; -} -// cppcheck-suppress uninitMemberVar -// cppcheck-suppress passedByValue -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, - Stream& stream) -{ - this->_state = MQTT_DISCONNECTED; - setServer(ip,port); - setCallback(callback); - setClient(client); - setStream(stream); -} -// cppcheck-suppress uninitMemberVar -PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) -{ - this->_state = MQTT_DISCONNECTED; - setServer(domain,port); - setClient(client); - this->stream = NULL; -} -// cppcheck-suppress uninitMemberVar -PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) -{ - this->_state = MQTT_DISCONNECTED; - setServer(domain,port); - setClient(client); - setStream(stream); -} -// cppcheck-suppress uninitMemberVar -// cppcheck-suppress passedByValue -PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, - Client& client) -{ - this->_state = MQTT_DISCONNECTED; - setServer(domain,port); - setCallback(callback); - setClient(client); - this->stream = NULL; -} -// cppcheck-suppress uninitMemberVar -// cppcheck-suppress passedByValue -PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, - Client& client, Stream& stream) -{ - this->_state = MQTT_DISCONNECTED; - setServer(domain,port); - setCallback(callback); - setClient(client); - setStream(stream); -} - -bool PubSubClient::connect(const char *id) -{ - return connect(id,NULL,NULL,0,0,0,0,1); -} - -bool PubSubClient::connect(const char *id, const char *user, const char *pass) -{ - return connect(id,user,pass,0,0,0,0,1); -} - -bool PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, - bool willRetain, const char* willMessage) -{ - return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage,1); -} - -bool PubSubClient::connect(const char *id, const char *user, const char *pass, - const char* willTopic, uint8_t willQos, bool willRetain, const char* willMessage) -{ - return connect(id,user,pass,willTopic,willQos,willRetain,willMessage,1); -} - -bool PubSubClient::connect(const char *id, const char *user, const char *pass, - const char* willTopic, uint8_t willQos, bool willRetain, const char* willMessage, - bool cleanSession) -{ - if (!connected()) { - int result = 0; - - if (domain != NULL) { - result = _client->connect(this->domain, this->port); - } else { - result = _client->connect(this->ip, this->port); - } - if (result == 1) { - nextMsgId = 1; - // Leave room in the buffer for header and variable length field - uint16_t length = MQTT_MAX_HEADER_SIZE; - unsigned int j; - -#if MQTT_VERSION == MQTT_VERSION_3_1 - uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION}; -#define MQTT_HEADER_VERSION_LENGTH 9 -#elif MQTT_VERSION == MQTT_VERSION_3_1_1 - uint8_t d[7] = {0x00,0x04,'M','Q','T','T',MQTT_VERSION}; -#define MQTT_HEADER_VERSION_LENGTH 7 -#endif - for (j = 0; j>1); - } - } - - buffer[length++] = v; - - buffer[length++] = ((MQTT_KEEPALIVE) >> 8); - buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); - - CHECK_STRING_LENGTH(length,id) - length = writeString(id,buffer,length); - if (willTopic) { - CHECK_STRING_LENGTH(length,willTopic) - length = writeString(willTopic,buffer,length); - CHECK_STRING_LENGTH(length,willMessage) - length = writeString(willMessage,buffer,length); - } - - if(user != NULL) { - CHECK_STRING_LENGTH(length,user) - length = writeString(user,buffer,length); - if(pass != NULL) { - CHECK_STRING_LENGTH(length,pass) - length = writeString(pass,buffer,length); - } - } - - write(MQTTCONNECT,buffer,length-MQTT_MAX_HEADER_SIZE); - - lastInActivity = lastOutActivity = millis(); - - while (!_client->available()) { - unsigned long t = millis(); - if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) { - _state = MQTT_CONNECTION_TIMEOUT; - _client->stop(); - return false; - } - } - uint8_t llen; - uint16_t len = readPacket(&llen); - - if (len == 4) { - if (buffer[3] == 0) { - lastInActivity = millis(); - pingOutstanding = false; - _state = MQTT_CONNECTED; - return true; - } else { - _state = buffer[3]; - } - } - _client->stop(); - } else { - _state = MQTT_CONNECT_FAILED; - } - return false; - } - return true; -} - -// reads a byte into result -bool PubSubClient::readByte(uint8_t * result) -{ - uint32_t previousMillis = millis(); - while(!_client->available()) { - yield(); - uint32_t currentMillis = millis(); - if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)) { - return false; - } - } - *result = _client->read(); - return true; -} - -// reads a byte into result[*index] and increments index -bool PubSubClient::readByte(uint8_t * result, uint16_t * index) -{ - uint16_t current_index = *index; - uint8_t * write_address = &(result[current_index]); - if(readByte(write_address)) { - *index = current_index + 1; - return true; - } - return false; -} - -uint16_t PubSubClient::readPacket(uint8_t* lengthLength) -{ - uint16_t len = 0; - if(!readByte(buffer, &len)) { - return 0; - } - bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; - uint32_t multiplier = 1; - uint16_t length = 0; - uint8_t digit = 0; - uint16_t skip = 0; - uint8_t start = 0; - - do { - if (len == 5) { - // Invalid remaining length encoding - kill the connection - _state = MQTT_DISCONNECTED; - _client->stop(); - return 0; - } - if(!readByte(&digit)) { - return 0; - } - buffer[len++] = digit; - length += (digit & 127) * multiplier; - multiplier *= 128; - } while ((digit & 128) != 0); - *lengthLength = len-1; - - if (isPublish) { - // Read in topic length to calculate bytes to skip over for Stream writing - if(!readByte(buffer, &len)) { - return 0; - } - if(!readByte(buffer, &len)) { - return 0; - } - skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; - start = 2; - if (buffer[0]&MQTTQOS1) { - // skip message id - skip += 2; - } - } - - for (uint16_t i = start; istream) { - if (isPublish && len-*lengthLength-2>skip) { - this->stream->write(digit); - } - } - if (len < MQTT_MAX_PACKET_SIZE) { - buffer[len] = digit; - } - len++; - } - - if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { - len = 0; // This will cause the packet to be ignored. - } - - return len; -} - -bool PubSubClient::loop() -{ - if (connected()) { - unsigned long t = millis(); - if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { - if (pingOutstanding) { - this->_state = MQTT_CONNECTION_TIMEOUT; - _client->stop(); - return false; - } else { - buffer[0] = MQTTPINGREQ; - buffer[1] = 0; - _client->write(buffer,2); - lastOutActivity = t; - lastInActivity = t; - pingOutstanding = true; - } - } - if (_client->available()) { - uint8_t llen; - uint16_t len = readPacket(&llen); - if (len > 0) { - lastInActivity = t; - uint8_t type = buffer[0]&0xF0; - if (type == MQTTPUBLISH) { - if (callback) { - uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */ - memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */ - buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */ - char *topic = (char*) buffer+llen+2; - uint8_t *payload; - // msgId only present for QOS>0 - if ((buffer[0]&0x06) == MQTTQOS1) { - uint16_t msgId = 0; - msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; - payload = buffer+llen+3+tl+2; - callback(topic,payload,len-llen-3-tl-2); - - buffer[0] = MQTTPUBACK; - buffer[1] = 2; - buffer[2] = (msgId >> 8); - buffer[3] = (msgId & 0xFF); - _client->write(buffer,4); - lastOutActivity = t; - - } else { - payload = buffer+llen+3+tl; - callback(topic,payload,len-llen-3-tl); - } - } - } else if (type == MQTTPINGREQ) { - buffer[0] = MQTTPINGRESP; - buffer[1] = 0; - _client->write(buffer,2); - } else if (type == MQTTPINGRESP) { - pingOutstanding = false; - } - } else if (!connected()) { - // readPacket has closed the connection - return false; - } - } - return true; - } - return false; -} - -bool PubSubClient::publish(const char* topic, const char* payload) -{ - return publish(topic,(const uint8_t*)payload,strlen(payload),false); -} - -bool PubSubClient::publish(const char* topic, const char* payload, bool retained) -{ - return publish(topic,(const uint8_t*)payload,strlen(payload),retained); -} - -bool PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) -{ - return publish(topic, payload, plength, false); -} - -bool PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, - bool retained) -{ - if (connected()) { - if (MQTT_MAX_PACKET_SIZE < MQTT_MAX_HEADER_SIZE + 2+strlen(topic) + plength) { - // Too long - return false; - } - // Leave room in the buffer for header and variable length field - uint16_t length = MQTT_MAX_HEADER_SIZE; - length = writeString(topic,buffer,length); - uint16_t i; - for (i=0; i 0) { - digit |= 0x80; - } - buffer[pos++] = digit; - } while(len>0); - - pos = writeString(topic,buffer,pos); - - rc += _client->write(buffer,pos); - - for (i=0; iwrite((char)pgm_read_byte_near(payload + i)); - } - - lastOutActivity = millis(); - - return rc == tlen + 4 + plength; -} - -bool PubSubClient::beginPublish(const char* topic, unsigned int plength, bool retained) -{ - if (connected()) { - // Send the header and variable length field - uint16_t length = MQTT_MAX_HEADER_SIZE; - length = writeString(topic,buffer,length); - uint8_t header = MQTTPUBLISH; - if (retained) { - header |= 1; - } - size_t hlen = buildHeader(header, buffer, plength+length-MQTT_MAX_HEADER_SIZE); - uint16_t rc = _client->write(buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen)); - lastOutActivity = millis(); - return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen))); - } - return false; -} - -int PubSubClient::endPublish() -{ - return 1; -} - -size_t PubSubClient::write(uint8_t data) -{ - lastOutActivity = millis(); - return _client->write(data); -} - -size_t PubSubClient::write(const uint8_t *buffer, size_t size) -{ - lastOutActivity = millis(); - return _client->write(buffer,size); -} - -size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length) -{ - uint8_t lenBuf[4]; - uint8_t llen = 0; - uint8_t pos = 0; - uint16_t len = length; - do { - uint8_t digit; - digit = len % 128; - len = len / 128; - if (len > 0) { - digit |= 0x80; - } - lenBuf[pos++] = digit; - llen++; - } while(len>0); - - buf[4-llen] = header; - for (int i=0; i 0) && result) { - bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining; - rc = _client->write(writeBuf,bytesToWrite); - result = (rc == bytesToWrite); - bytesRemaining -= rc; - writeBuf += rc; - } - return result; -#else - rc = _client->write(buf+(MQTT_MAX_HEADER_SIZE-hlen),length+hlen); - lastOutActivity = millis(); - return (rc == hlen+length); -#endif -} - -bool PubSubClient::subscribe(const char* topic) -{ - return subscribe(topic, 0); -} - -bool PubSubClient::subscribe(const char* topic, uint8_t qos) -{ - if (qos > 1) { - return false; - } - if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { - // Too long - return false; - } - if (connected()) { - // Leave room in the buffer for header and variable length field - uint16_t length = MQTT_MAX_HEADER_SIZE; - nextMsgId++; - if (nextMsgId == 0) { - nextMsgId = 1; - } - buffer[length++] = (nextMsgId >> 8); - buffer[length++] = (nextMsgId & 0xFF); - length = writeString((char*)topic, buffer,length); - buffer[length++] = qos; - return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE); - } - return false; -} - -bool PubSubClient::unsubscribe(const char* topic) -{ - if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { - // Too long - return false; - } - if (connected()) { - uint16_t length = MQTT_MAX_HEADER_SIZE; - nextMsgId++; - if (nextMsgId == 0) { - nextMsgId = 1; - } - buffer[length++] = (nextMsgId >> 8); - buffer[length++] = (nextMsgId & 0xFF); - length = writeString(topic, buffer,length); - return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE); - } - return false; -} - -void PubSubClient::disconnect() -{ - buffer[0] = MQTTDISCONNECT; - buffer[1] = 0; - _client->write(buffer,2); - _state = MQTT_DISCONNECTED; - _client->flush(); - _client->stop(); - lastInActivity = lastOutActivity = millis(); -} - -uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) -{ - const char* idp = string; - uint16_t i = 0; - pos += 2; - while (*idp) { - buf[pos++] = *idp++; - i++; - } - buf[pos-i-2] = (i >> 8); - buf[pos-i-1] = (i & 0xFF); - return pos; -} - - -bool PubSubClient::connected() -{ - bool rc; - if (_client == NULL ) { - rc = false; - } else { - rc = (int)_client->connected(); - if (!rc) { - if (this->_state == MQTT_CONNECTED) { - this->_state = MQTT_CONNECTION_LOST; - _client->flush(); - _client->stop(); - } - } - } - return rc; -} - -PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) -{ - IPAddress addr(ip[0],ip[1],ip[2],ip[3]); - return setServer(addr,port); -} - -PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) -{ - this->ip = ip; - this->port = port; - this->domain = NULL; - return *this; -} - -PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) -{ - this->domain = domain; - this->port = port; - return *this; -} -// cppcheck-suppress passedByValue -PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) -{ - this->callback = callback; - return *this; -} - -PubSubClient& PubSubClient::setClient(Client& client) -{ - this->_client = &client; - return *this; -} - -PubSubClient& PubSubClient::setStream(Stream& stream) -{ - this->stream = &stream; - return *this; -} - -int PubSubClient::state() -{ - return this->_state; -} diff --git a/lib/MySensors/drivers/PubSubClient/PubSubClient.h b/lib/MySensors/drivers/PubSubClient/PubSubClient.h deleted file mode 100644 index 7332375a..00000000 --- a/lib/MySensors/drivers/PubSubClient/PubSubClient.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - PubSubClient.h - A simple client for MQTT. - Nick O'Leary - http://knolleary.net -*/ - -#ifndef PubSubClient_h -#define PubSubClient_h - -#include -#include "IPAddress.h" -#include "Client.h" -#include "Stream.h" - -#define MQTT_VERSION_3_1 3 -#define MQTT_VERSION_3_1_1 4 - -// MQTT_VERSION : Pick the version -//#define MQTT_VERSION MQTT_VERSION_3_1 -#ifndef MQTT_VERSION -#define MQTT_VERSION MQTT_VERSION_3_1_1 -#endif - -// MQTT_MAX_PACKET_SIZE : Maximum packet size -#ifndef MQTT_MAX_PACKET_SIZE -#define MQTT_MAX_PACKET_SIZE 128 -#endif - -// MQTT_KEEPALIVE : keepAlive interval in Seconds -#ifndef MQTT_KEEPALIVE -#define MQTT_KEEPALIVE 15 -#endif - -// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds -#ifndef MQTT_SOCKET_TIMEOUT -#define MQTT_SOCKET_TIMEOUT 15 -#endif - -// MQTT_MAX_TRANSFER_SIZE : limit how much data is passed to the network client -// in each write call. Needed for the Arduino Wifi Shield. Leave undefined to -// pass the entire MQTT packet in each write call. -//#define MQTT_MAX_TRANSFER_SIZE 80 - -// Possible values for client.state() -#define MQTT_CONNECTION_TIMEOUT -4 -#define MQTT_CONNECTION_LOST -3 -#define MQTT_CONNECT_FAILED -2 -#define MQTT_DISCONNECTED -1 -#define MQTT_CONNECTED 0 -#define MQTT_CONNECT_BAD_PROTOCOL 1 -#define MQTT_CONNECT_BAD_CLIENT_ID 2 -#define MQTT_CONNECT_UNAVAILABLE 3 -#define MQTT_CONNECT_BAD_CREDENTIALS 4 -#define MQTT_CONNECT_UNAUTHORIZED 5 - -#define MQTTCONNECT 1 << 4 // Client request to connect to Server -#define MQTTCONNACK 2 << 4 // Connect Acknowledgment -#define MQTTPUBLISH 3 << 4 // Publish message -#define MQTTPUBACK 4 << 4 // Publish Acknowledgment -#define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1) -#define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2) -#define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3) -#define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request -#define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment -#define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request -#define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment -#define MQTTPINGREQ 12 << 4 // PING Request -#define MQTTPINGRESP 13 << 4 // PING Response -#define MQTTDISCONNECT 14 << 4 // Client is Disconnecting -#define MQTTReserved 15 << 4 // Reserved - -#define MQTTQOS0 (0 << 1) -#define MQTTQOS1 (1 << 1) -#define MQTTQOS2 (2 << 1) - -// Maximum size of fixed header and variable length size header -#define MQTT_MAX_HEADER_SIZE 5 - -#if defined(ESP8266) || defined(ESP32) -#include -#define MQTT_CALLBACK_SIGNATURE std::function callback -#else -#define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int) -#endif - -#define CHECK_STRING_LENGTH(l,s) if (l+2+strlen(s) > MQTT_MAX_PACKET_SIZE) {_client->stop();return false;} - -/** PubSubClient class */ -class PubSubClient : public Print -{ -private: - Client* _client; - uint8_t buffer[MQTT_MAX_PACKET_SIZE]; - uint16_t nextMsgId; - unsigned long lastOutActivity; - unsigned long lastInActivity; - bool pingOutstanding; - MQTT_CALLBACK_SIGNATURE; - uint16_t readPacket(uint8_t*); - bool readByte(uint8_t * result); - bool readByte(uint8_t * result, uint16_t * index); - bool write(uint8_t header, uint8_t* buf, uint16_t length); - uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); - // Build up the header ready to send - // Returns the size of the header - // Note: the header is built at the end of the first MQTT_MAX_HEADER_SIZE bytes, so will start - // (MQTT_MAX_HEADER_SIZE - ) bytes into the buffer - size_t buildHeader(uint8_t header, uint8_t* buf, uint16_t length); - IPAddress ip; - const char* domain; - uint16_t port; - Stream* stream; - int _state; -public: - PubSubClient(); //!< PubSubClient - explicit PubSubClient(Client& client); //!< PubSubClient - PubSubClient(IPAddress, uint16_t, Client& client); //!< PubSubClient - PubSubClient(IPAddress, uint16_t, Client& client, Stream&); //!< PubSubClient - PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient - PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, - Stream&); //!< PubSubClient - PubSubClient(uint8_t *, uint16_t, Client& client); //!< PubSubClient - PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); //!< PubSubClient - PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient - PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, - Stream&); //!< PubSubClient - PubSubClient(const char*, uint16_t, Client& client); //!< PubSubClient - PubSubClient(const char*, uint16_t, Client& client, Stream&); //!< PubSubClient - PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient - PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, - Stream&); //!< PubSubClient - - PubSubClient& setServer(IPAddress ip, uint16_t port); //!< setServer - PubSubClient& setServer(uint8_t * ip, uint16_t port); //!< setServer - PubSubClient& setServer(const char * domain, uint16_t port); //!< setServer - PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE); //!< setCallback - PubSubClient& setClient(Client& client); //!< setClient - PubSubClient& setStream(Stream& stream); //!< setStream - - bool connect(const char* id); //!< connect - bool connect(const char* id, const char* user, const char* pass); //!< connect - bool connect(const char* id, const char* willTopic, uint8_t willQos, bool willRetain, - const char* willMessage); //!< connect - bool connect(const char* id, const char* user, const char* pass, const char* willTopic, - uint8_t willQos, bool willRetain, const char* willMessage); //!< connect - bool connect(const char* id, const char* user, const char* pass, const char* willTopic, - uint8_t willQos, bool willRetain, const char* willMessage, bool cleanSession); //!< connect - void disconnect(); //!< disconnect - bool publish(const char* topic, const char* payload); //!< publish - bool publish(const char* topic, const char* payload, bool retained); //!< publish - bool publish(const char* topic, const uint8_t * payload, unsigned int plength); //!< publish - bool publish(const char* topic, const uint8_t * payload, unsigned int plength, - bool retained); //!< publish - bool publish_P(const char* topic, const char* payload, bool retained); //!< publish - bool publish_P(const char* topic, const uint8_t * payload, unsigned int plength, - bool retained); //!< publish - // Start to publish a message. - // This API: - // beginPublish(...) - // one or more calls to write(...) - // endPublish() - // Allows for arbitrarily large payloads to be sent without them having to be copied into - // a new buffer and held in memory at one time - // Returns 1 if the message was started successfully, 0 if there was an error - bool beginPublish(const char* topic, unsigned int plength, bool retained); //!< beginPublish - // Finish off this publish message (started with beginPublish) - // Returns 1 if the packet was sent successfully, 0 if there was an error - int endPublish(); //!< endPublish - // Write a single byte of payload (only to be used with beginPublish/endPublish) - virtual size_t write(uint8_t); //!< write - // Write size bytes from buffer into the payload (only to be used with beginPublish/endPublish) - // Returns the number of bytes written - virtual size_t write(const uint8_t *buffer, size_t size); //!< write - bool subscribe(const char* topic); //!< subscribe - bool subscribe(const char* topic, uint8_t qos); //!< subscribe - bool unsubscribe(const char* topic); //!< unsubscribe - bool loop(); //!< loop - bool connected(); //!< connected - int state(); //!< state -}; - - -#endif diff --git a/lib/MySensors/drivers/PubSubClient/README.md b/lib/MySensors/drivers/PubSubClient/README.md deleted file mode 100644 index 69cbb8f0..00000000 --- a/lib/MySensors/drivers/PubSubClient/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# Arduino Client for MQTT - -This library provides a client for doing simple publish/subscribe messaging with -a server that supports MQTT. - -## Examples - -The library comes with a number of example sketches. See File > Examples > PubSubClient -within the Arduino application. - -Full API documentation is available here: https://pubsubclient.knolleary.net - -## Limitations - - - It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1. - - The maximum message size, including header, is **128 bytes** by default. This - is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h`. - - The keepalive interval is set to 15 seconds by default. This is configurable - via `MQTT_KEEPALIVE` in `PubSubClient.h`. - - The client uses MQTT 3.1.1 by default. It can be changed to use MQTT 3.1 by - changing value of `MQTT_VERSION` in `PubSubClient.h`. - - -## Compatible Hardware - -The library uses the Arduino Ethernet Client api for interacting with the -underlying network hardware. This means it Just Works with a growing number of -boards and shields, including: - - - Arduino Ethernet - - Arduino Ethernet Shield - - Arduino YUN – use the included `YunClient` in place of `EthernetClient`, and - be sure to do a `Bridge.begin()` first - - Arduino WiFi Shield - if you want to send packets > 90 bytes with this shield, - enable the `MQTT_MAX_TRANSFER_SIZE` define in `PubSubClient.h`. - - Sparkfun WiFly Shield – [library](https://github.com/dpslwk/WiFly) - - TI CC3000 WiFi - [library](https://github.com/sparkfun/SFE_CC3000_Library) - - Intel Galileo/Edison - - ESP8266 - - ESP32 - -The library cannot currently be used with hardware based on the ENC28J60 chip – -such as the Nanode or the Nuelectronics Ethernet Shield. For those, there is an -[alternative library](https://github.com/njh/NanodeMQTT) available. - -## License - -This code is released under the MIT License. diff --git a/lib/MySensors/drivers/SPIFlash/License.txt b/lib/MySensors/drivers/SPIFlash/License.txt deleted file mode 100644 index 94a9ed02..00000000 --- a/lib/MySensors/drivers/SPIFlash/License.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/lib/MySensors/drivers/SPIFlash/README.md b/lib/MySensors/drivers/SPIFlash/README.md deleted file mode 100644 index 3a7a7ba3..00000000 --- a/lib/MySensors/drivers/SPIFlash/README.md +++ /dev/null @@ -1,32 +0,0 @@ -SPIFlash -======== -[![Build Status](https://travis-ci.org/LowPowerLab/SPIFlash.svg?branch=master)](https://travis-ci.org/LowPowerLab/SPIFlash) -[![GitHub release](https://img.shields.io/github/release/LowPowerLab/SPIFlash.svg)](https://github.com/LowPowerLab/SPIFlash) -[![GitHub issues](https://img.shields.io/github/issues/LowPowerLab/SPIFlash.svg)](https://github.com/LowPowerLab/SPIFlash/issues) -[![GitHub pull requests](https://img.shields.io/github/issues-pr/LowPowerLab/SPIFlash.svg)](https://github.com/LowPowerLab/SPIFlash/pulls) -[![license](https://img.shields.io/github/license/LowPowerLab/SPIFlash.svg)](https://github.com/LowPowerLab/SPIFlash/blob/master/LICENSE.txt) - -Arduino/Moteino library for read/write access to SPI flash memory chips. -This works with 256byte/page SPI flash memory such as the [4MBIT W25X40CLSNIG](https://lowpowerlab.com/shop/product/72) used on [Moteino](https://www.moteino.com) for data storage and wireless programming. -
-For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes). -
Minimal modifications should allow chips that have different page size to work. -
DEPENDS ON: Arduino native *SPI library*. -
-This library was primarily developed to enable **safe** wireless programming on Moteino nodes and Moteino based applications such as the [SwitchMote](https://lowpowerlab.com/guide/switchmote/). This has been documented at [lowpowerlab](https://lowpowerlab.com/guide/moteino/wireless-programming/). [Dualoptiboot](https://github.com/LowPowerLab/DualOptiboot) (all AVR based Moteinos come with it) and [RFM69_OTA WirelessProgramming library](https://github.com/LowPowerLab/RFM69) are required to be able to wirelessly re-flash a remote Moteino. - -### Installation -Copy the content of this library in the "Arduino/libraries/SPIFlash" folder. -
-To find your Arduino folder go to File>Preferences in the Arduino IDE. -
-See [this tutorial](https://www.arduino.cc/en/Guide/Libraries) on installing Arduino libraries. - -### License -Copyright (c) 2013-2018 by Felix Rusu -

-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/lib/MySensors/drivers/SPIFlash/SPIFlash.cpp b/lib/MySensors/drivers/SPIFlash/SPIFlash.cpp deleted file mode 100644 index b966e089..00000000 --- a/lib/MySensors/drivers/SPIFlash/SPIFlash.cpp +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright (c) 2013-2015 by Felix Rusu, LowPowerLab.com -// SPI Flash memory library for arduino/moteino. -// This works with 256byte/page SPI flash memory -// For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes) -// Minimal modifications should allow chips that have different page size but modifications -// DEPENDS ON: Arduino SPI library -// > Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment. -// > Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above) -// > Selective merge by Felix after testing in IDE 1.0.6, 1.6.4 -// > Updated May 19, 2016 D-H-R, added support for SST25/Microchip Flash which does not support Page programming with OPCode 0x02, -// > use define MY_SPIFLASH_SST25TYPE for SST25 Type Flash Memory -// > Updated Sep 07, 2018 tekka, sync with https://github.com/LowPowerLab/SPIFlash -// ********************************************************************************** -// License -// ********************************************************************************** -// 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 . -// -// Licence can be viewed at -// http://www.gnu.org/licenses/gpl-3.0.txt -// -// Please maintain this license information along with authorship -// and copyright notices in any redistribution of this code - -#include "SPIFlash.h" - -uint8_t SPIFlash::UNIQUEID[8]; - -/// IMPORTANT: NAND FLASH memory requires erase before write, because -/// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s -/// See http://en.wikipedia.org/wiki/Flash_memory -/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command - -/// Constructor. JedecID is optional but recommended, since this will ensure that the device is present and has a valid response -/// get this from the datasheet of your flash chip -/// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) -/// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) -// Suppress uninitialized member variable in constructor because some memory can be saved with -// on-demand initialization of these members -// cppcheck-suppress uninitMemberVar -SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) -{ - _slaveSelectPin = slaveSelectPin; - _jedecID = jedecID; -} - -/// Select the flash chip -void SPIFlash::select() -{ - //save current SPI settings -#ifndef SPI_HAS_TRANSACTION - noInterrupts(); -#endif -#if defined(SPCR) && defined(SPSR) - _SPCR = SPCR; - _SPSR = SPSR; -#endif - -#ifdef SPI_HAS_TRANSACTION - SPI.beginTransaction(_settings); -#else - // set FLASH SPI settings - SPI.setDataMode(SPI_MODE0); - SPI.setBitOrder(MSBFIRST); - SPI.setClockDivider( - SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present -#endif - hwDigitalWrite(_slaveSelectPin, LOW); -} - -/// UNselect the flash chip -void SPIFlash::unselect() -{ - hwDigitalWrite(_slaveSelectPin, HIGH); - //restore SPI settings to what they were before talking to the FLASH chip -#ifdef SPI_HAS_TRANSACTION - SPI.endTransaction(); -#else - interrupts(); -#endif -#if defined(SPCR) && defined(SPSR) - SPCR = _SPCR; - SPSR = _SPSR; -#endif -} - -/// setup SPI, read device ID etc... -bool SPIFlash::initialize() -{ -#if defined(SPCR) && defined(SPSR) - _SPCR = SPCR; - _SPSR = SPSR; -#endif - hwPinMode(_slaveSelectPin, OUTPUT); - SPI.begin(); // see https://github.com/LowPowerLab/SPIFlash/issues/20 -#ifdef SPI_HAS_TRANSACTION - _settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); -#endif - - unselect(); - wakeup(); - - if (_jedecID == 0 || readDeviceId() == _jedecID) { - command(SPIFLASH_STATUSWRITE, true); // Write Status Register - SPI.transfer(0); // Global Unprotect - unselect(); - return true; - } - return false; -} - -/// Get the manufacturer and device ID bytes (as a short word) -uint16_t SPIFlash::readDeviceId() -{ -#if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo - command(SPIFLASH_IDREAD); // Read JEDEC ID -#else - select(); - SPI.transfer(SPIFLASH_IDREAD); -#endif - uint16_t jedecid = SPI.transfer(0) << 8; - jedecid |= SPI.transfer(0); - unselect(); - return jedecid; -} - -/// Get the 64 bit unique identifier, stores it in UNIQUEID[8]. Only needs to be called once, ie after initialize -/// Returns the byte pointer to the UNIQUEID byte array -/// Read UNIQUEID like this: -/// flash.readUniqueId(); for (uint8_t i=0;i<8;i++) { Serial.print(flash.UNIQUEID[i], HEX); Serial.print(' '); } -/// or like this: -/// flash.readUniqueId(); uint8_t* MAC = flash.readUniqueId(); for (uint8_t i=0;i<8;i++) { Serial.print(MAC[i], HEX); Serial.print(' '); } -uint8_t* SPIFlash::readUniqueId() -{ - command(SPIFLASH_MACREAD); - SPI.transfer(0); - SPI.transfer(0); - SPI.transfer(0); - SPI.transfer(0); - for (uint8_t i=0; i<8; i++) { - UNIQUEID[i] = SPI.transfer(0); - } - unselect(); - return UNIQUEID; -} - -/// read 1 byte from flash memory -uint8_t SPIFlash::readByte(uint32_t addr) -{ - command(SPIFLASH_ARRAYREADLOWFREQ); - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - uint8_t result = SPI.transfer(0); - unselect(); - return result; -} - -/// read unlimited # of bytes -void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) -{ - command(SPIFLASH_ARRAYREAD); - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - SPI.transfer(0); //"dont care" - for (uint16_t i = 0; i < len; ++i) { - ((uint8_t*) buf)[i] = SPI.transfer(0); - } - unselect(); -} - -/// Send a command to the flash chip, pass TRUE for isWrite when its a write command -void SPIFlash::command(uint8_t cmd, bool isWrite) -{ -#if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo - DDRB |= B00000001; // Make sure the SS pin (PB0 - used by RFM12B on MoteinoLeo R1) is set as output HIGH! - PORTB |= B00000001; -#endif - if (isWrite) { - command(SPIFLASH_WRITEENABLE); // Write Enable - unselect(); - } - //wait for any write/erase to complete - // a time limit cannot really be added here without it being a very large safe limit - // that is because some chips can take several seconds to carry out a chip erase or other similar multi block or entire-chip operations - // a recommended alternative to such situations where chip can be or not be present is to add a 10k or similar weak pulldown on the - // open drain MISO input which can read noise/static and hence return a non 0 status byte, causing the while() to hang when a flash chip is not present - if (cmd != SPIFLASH_WAKE) while(busy()); - select(); - SPI.transfer(cmd); -} - -/// check if the chip is busy erasing/writing -bool SPIFlash::busy() -{ - /* - select(); - SPI.transfer(SPIFLASH_STATUSREAD); - uint8_t status = SPI.transfer(0); - unselect(); - return status & 1; - */ - return readStatus() & 1; -} - -/// return the STATUS register -uint8_t SPIFlash::readStatus() -{ - select(); - SPI.transfer(SPIFLASH_STATUSREAD); - uint8_t status = SPI.transfer(0); - unselect(); - return status; -} - - -/// Write 1 byte to flash memory -/// WARNING: you can only write to previously erased memory locations (see datasheet) -/// use the block erase commands to first clear memory (write 0xFFs) -void SPIFlash::writeByte(uint32_t addr, uint8_t byt) -{ - command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - SPI.transfer(byt); - unselect(); -} - -/// write multiple bytes to flash memory (up to 64K) -/// WARNING: you can only write to previously erased memory locations (see datasheet) -/// use the block erase commands to first clear memory (write 0xFFs) -/// This version handles both page alignment and data blocks larger than 256 bytes. -/// See documentation of #MY_SPIFLASH_SST25TYPE define for more information -void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) -{ -#ifdef MY_SPIFLASH_SST25TYPE - //SST25 Type of Flash does not support Page Programming but AAI Word Programming - uint16_t i=0; - uint8_t oddAdr=0; - - command(SPIFLASH_AAIWORDPROGRAM, true); // Byte/Page Program - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - - if (addr%2) { - //start address is not even, i.e. first byte of word must be 0xff - SPI.transfer(0xff); - SPI.transfer(((uint8_t*) buf)[0]); - unselect(); - oddAdr=1; //following addresses must all be shifted one off - len--; - if (len > 0) { - command(SPIFLASH_AAIWORDPROGRAM); //If for loop will run issue Wordprogram command - } - } - - for (i=0; i<(len/2); i++) { - //AAI command must be set before every new word - if (i>0) { - command(SPIFLASH_AAIWORDPROGRAM); //Wordprogram command for first write has been issued before - } - SPI.transfer(((uint8_t*) buf)[i*2+oddAdr]); - SPI.transfer(((uint8_t*) buf)[i*2+1+oddAdr]); - unselect(); - } - - if (len-i*2 == 1) { - //There is one byte (i.e. half word) left. This happens if len was odd or (len was even and addr odd) - if (i>0) { - command(SPIFLASH_AAIWORDPROGRAM); //if for loop had not run wordprogram command from before is still valid - } - SPI.transfer(((uint8_t*) buf)[i*2+oddAdr]); - SPI.transfer(0xff); - unselect(); - } - - command(SPIFLASH_WRITEDISABLE); //end AAI programming - unselect(); -#else - uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page - uint16_t offset = 0; - while (len>0) { - uint16_t n = (len<=maxBytes) ? len : maxBytes; - command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - - for (uint16_t i = 0; i < n; i++) { - SPI.transfer(((uint8_t*) buf)[offset + i]); - } - unselect(); - - addr+=n; // adjust the addresses and remaining bytes by what we've just transferred. - offset +=n; - len -= n; - maxBytes = 256; // now we can do up to 256 bytes per loop - } -#endif -} - -/// erase entire flash memory array -/// may take several seconds depending on size, but is non blocking -/// so you may wait for this to complete using busy() or continue doing -/// other things and later check if the chip is done with busy() -/// note that any command will first wait for chip to become available using busy() -/// so no need to do that twice -void SPIFlash::chipErase() -{ - command(SPIFLASH_CHIPERASE, true); - unselect(); -} - -/// erase a 4Kbyte block -void SPIFlash::blockErase4K(uint32_t addr) -{ - command(SPIFLASH_BLOCKERASE_4K, true); // Block Erase - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - unselect(); -} - -/// erase a 32Kbyte block -void SPIFlash::blockErase32K(uint32_t addr) -{ - command(SPIFLASH_BLOCKERASE_32K, true); // Block Erase - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - unselect(); -} -/// erase a 64Kbyte block -void SPIFlash::blockErase64K(uint32_t addr) -{ - command(SPIFLASH_BLOCKERASE_64K, true); // Block Erase - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - unselect(); -} - -void SPIFlash::sleep() -{ - command(SPIFLASH_SLEEP); - unselect(); -} - -void SPIFlash::wakeup() -{ - command(SPIFLASH_WAKE); - unselect(); -} - -/// cleanup -void SPIFlash::end() -{ - SPI.end(); -} diff --git a/lib/MySensors/drivers/SPIFlash/SPIFlash.h b/lib/MySensors/drivers/SPIFlash/SPIFlash.h deleted file mode 100644 index 89b7cb6a..00000000 --- a/lib/MySensors/drivers/SPIFlash/SPIFlash.h +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 2013-2015 by Felix Rusu, LowPowerLab.com -// SPI Flash memory library for arduino/moteino. -// This works with 256byte/page SPI flash memory -// For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes) -// Minimal modifications should allow chips that have different page size but modifications -// DEPENDS ON: Arduino SPI library -// > Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment. -// > Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above) -// > Selective merge by Felix after testing in IDE 1.0.6, 1.6.4 -// > Updated May 19, 2016 D-H-R, added support for SST25/Microchip Flash which does not support Page programming with OPCode 0x02, -// > use define MY_SPIFLASH_SST25TYPE for SST25 Type Flash Memory. Added / changed comments to better suit doxygen -// > Updated Sep 07, 2018 tekka, sync with https://github.com/LowPowerLab/SPIFlash -// ********************************************************************************** -// License -// ********************************************************************************** -// 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 . -// -// Licence can be viewed at -// http://www.gnu.org/licenses/gpl-3.0.txt -// -// Please maintain this license information along with authorship -// and copyright notices in any redistribution of this code - -/// -/// @file SPIFlash.h -/// -/// @brief SPIFlash provides access to a SPI Flash IC for OTA update or storing data -/// -/// IMPORTANT: NAND FLASH memory requires erase before write, because -/// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s -/// See http://en.wikipedia.org/wiki/Flash_memory -/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command -/// -/// Standard SPI flash commands
-/// Assuming the WP pin is pulled up (to disable hardware write protection).
-/// To use any write commands the WEL bit in the status register must be set to 1.
-/// This is accomplished by sending a 0x06 command before any such write/erase command.
-/// The WEL bit in the status register resets to the logical ?0? state after a device power-up or reset. -/// In addition, the WEL bit will be reset to the logical ?0? state automatically under the following conditions:
-/// - Write Disable operation completes successfully
-/// - Write Status Register operation completes successfully or aborts
-/// - Protect Sector operation completes successfully or aborts
-/// - Unprotect Sector operation completes successfully or aborts
-/// - Byte/Page Program operation completes successfully or aborts
-/// - Sequential Program Mode reaches highest unprotected memory location
-/// - Sequential Program Mode reaches the end of the memory array
-/// - Sequential Program Mode aborts
-/// - Block Erase operation completes successfully or aborts
-/// - Chip Erase operation completes successfully or aborts
-/// - Hold condition aborts -/// - -#ifndef _SPIFLASH_H_ -#define _SPIFLASH_H_ - -#if ARDUINO >= 100 -#include -#else -#include -#include "pins_arduino.h" -#endif - -#include - -#ifndef SPIFLASH_WRITEENABLE -#define SPIFLASH_WRITEENABLE 0x06 //!< write enable -#endif - -#ifndef SPIFLASH_WRITEDISABLE -#define SPIFLASH_WRITEDISABLE 0x04 //!< write disable -#endif - -#ifndef SPIFLASH_BLOCKERASE_4K -#define SPIFLASH_BLOCKERASE_4K 0x20 //!< erase one 4K block of flash memory -#endif - -#ifndef SPIFLASH_BLOCKERASE_32K -#define SPIFLASH_BLOCKERASE_32K 0x52 //!< erase one 32K block of flash memory -#endif - -#ifndef SPIFLASH_BLOCKERASE_64K -#define SPIFLASH_BLOCKERASE_64K 0xD8 //!< erase one 64K block of flash memory -#endif - -#ifndef SPIFLASH_CHIPERASE -#define SPIFLASH_CHIPERASE 0x60 //!< @brief chip erase (may take several seconds depending on size) -#endif -//!< Chip is erased but not actually waited for completion (instead need to check the status register BUSY bit) - -#ifndef SPIFLASH_STATUSREAD -#define SPIFLASH_STATUSREAD 0x05 //!< read status register -#endif - -#ifndef SPIFLASH_STATUSWRITE -#define SPIFLASH_STATUSWRITE 0x01 //!< write status register -#endif - -#ifndef SPIFLASH_ARRAYREAD -#define SPIFLASH_ARRAYREAD 0x0B //!< read array (fast, need to add 1 dummy byte after 3 address bytes) -#endif - -#ifndef SPIFLASH_ARRAYREADLOWFREQ -#define SPIFLASH_ARRAYREADLOWFREQ 0x03 //!< read array (low frequency) -#endif - -#ifndef SPIFLASH_SLEEP -#define SPIFLASH_SLEEP 0xB9 //!< deep power down -#endif - -#ifndef SPIFLASH_WAKE -#define SPIFLASH_WAKE 0xAB //!< deep power wake up -#endif - -#ifndef SPIFLASH_BYTEPAGEPROGRAM -#define SPIFLASH_BYTEPAGEPROGRAM 0x02 //!< write (1 to 256bytes). Writing more than one Byte is not supported on all devices (e.g. SST25 Series) -#endif - -#ifndef SPIFLASH_AAIWORDPROGRAM -#define SPIFLASH_AAIWORDPROGRAM 0xAD //!< @brief Auto Address Increment Programming on Microchip SST Family Devices which do not support page program.
-#endif -//!< Use define #MY_SPIFLASH_SST25TYPE to use AAI prog instead of Bytepageprogram which does not work on SST Family Chips -//!< tested with SST25PF020B80 http://ww1.microchip.com/downloads/en/DeviceDoc/20005135B.pdf - -#ifndef SPIFLASH_IDREAD -#define SPIFLASH_IDREAD 0x9F //!< @brief read JEDEC manufacturer and device ID (2 bytes, specific bytes for each manufacturer and device) -#endif -//!< Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) -//!< Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) - -#ifndef SPIFLASH_MACREAD -#define SPIFLASH_MACREAD 0x4B //!< read unique ID number (MAC) -#endif - -/// -/// @def MY_SPIFLASH_SST25TYPE -/// @brief If set AAI Word Programming is used to support SST25 Family SPI Flash. -/// -/// SST25 Family Flash does not support programming multiple Bytes with opcode 0x02 #SPIFLASH_BYTEPAGEPROGRAM.
-/// If SPIFLASH_SST25TYPE is set and writeBytes is called, it will use opcode 0xAD #SPIFLASH_AAIWORDPROGRAM and care for Byte alignment.
-/// Note: AAI Wordprogramming is independent of Pages, so pagebreaking is not an issue when using AAI Wordprogramming. -/// -#ifdef DOXYGEN //needed to tell doxygen not to ignore the define which is actually made somewhere else -#define MY_SPIFLASH_SST25TYPE -#endif - -/** SPIFlash class */ -class SPIFlash -{ -public: - static uint8_t UNIQUEID[8]; //!< Storage for unique identifier - explicit SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0); //!< Constructor - bool initialize(); //!< setup SPI, read device ID etc... - void command(uint8_t cmd, bool isWrite= - false); //!< Send a command to the flash chip, pass TRUE for isWrite when its a write command - uint8_t readStatus(); //!< return the STATUS register - uint8_t readByte(uint32_t addr); //!< read 1 byte from flash memory - void readBytes(uint32_t addr, void* buf, uint16_t len); //!< read unlimited # of bytes - void writeByte(uint32_t addr, uint8_t byt); //!< Write 1 byte to flash memory - void writeBytes(uint32_t addr, const void* buf, - uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used - bool busy(); //!< check if the chip is busy erasing/writing - void chipErase(); //!< erase entire flash memory array - void blockErase4K(uint32_t address); //!< erase a 4Kbyte block - void blockErase32K(uint32_t address); //!< erase a 32Kbyte block - void blockErase64K(uint32_t addr); //!< erase a 64Kbyte block - uint16_t readDeviceId(); //!< Get the manufacturer and device ID bytes (as a short word) - uint8_t* readUniqueId(); //!< Get the 64 bit unique identifier, stores it in @ref UNIQUEID[8] - - void sleep(); //!< Put device to sleep - void wakeup(); //!< Wake device - void end(); //!< end -protected: - void select(); //!< select - void unselect(); //!< unselect - uint8_t _slaveSelectPin; //!< Slave select pin - uint16_t _jedecID; //!< JEDEC ID - uint8_t _SPCR; //!< SPCR - uint8_t _SPSR; //!< SPSR -#ifdef SPI_HAS_TRANSACTION - SPISettings _settings; -#endif -}; - -#endif diff --git a/lib/MySensors/drivers/SPIFlash/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino b/lib/MySensors/drivers/SPIFlash/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino deleted file mode 100644 index d2350507..00000000 --- a/lib/MySensors/drivers/SPIFlash/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino +++ /dev/null @@ -1,127 +0,0 @@ -// ********************************************************************************** -// This sketch is an example of using the SPIFlash library with a Moteino -// that has an onboard SPI Flash chip. This sketch listens to a few serial commands -// Hence type the following commands to interact with the SPI flash memory array: -// - 'd' dumps the first 256bytes of the flash chip to screen -// - 'e' erases the entire memory chip -// - 'i' print manufacturer/device ID -// - [0-9] writes a random byte to addresses [0-9] (either 0xAA or 0xBB) -// Get the SPIFlash library from here: https://github.com/LowPowerLab/SPIFlash -// ********************************************************************************** -// Copyright Felix Rusu, LowPowerLab.com -// Library and code by Felix Rusu - felix@lowpowerlab.com -// ********************************************************************************** -// License -// ********************************************************************************** -// 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 . -// -// Licence can be viewed at -// http://www.gnu.org/licenses/gpl-3.0.txt -// -// Please maintain this license information along with authorship -// and copyright notices in any redistribution of this code -// ********************************************************************************** - - -#include //get it here: https://github.com/LowPowerLab/SPIFlash -#include - -#define SERIAL_BAUD 115200 -char input = 0; -long lastPeriod = -1; - -#ifdef __AVR_ATmega1284P__ -#define LED 15 // Moteino MEGAs have LEDs on D15 -#define FLASH_SS 23 // and FLASH SS on D23 -#else -#define LED 9 // Moteinos have LEDs on D9 -#define FLASH_SS 8 // and FLASH SS on D8 -#endif - -////////////////////////////////////////// -// flash(SPI_CS, MANUFACTURER_ID) -// SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino) -// MANUFACTURER_ID - OPTIONAL, 0x1F44 for adesto(ex atmel) 4mbit flash -// 0xEF30 for windbond 4mbit flash -////////////////////////////////////////// -SPIFlash flash(FLASH_SS, 0xEF30); - -void setup() -{ - Serial.begin(SERIAL_BAUD); - Serial.print("Start..."); - - if (flash.initialize()) { - Serial.println("Init OK!"); - Blink(LED, 20, 10); - } else { - Serial.println("Init FAIL!"); - } - - delay(1000); -} - -void loop() -{ - // Handle serial input (to allow basic DEBUGGING of FLASH chip) - // ie: display first 256 bytes in FLASH, erase chip, write bytes at first 10 positions, etc - if (Serial.available() > 0) { - input = Serial.read(); - if (input == 'd') { //d=dump flash area - Serial.println("Flash content:"); - int counter = 0; - - while(counter<=256) { - Serial.print(flash.readByte(counter++), HEX); - Serial.print('.'); - } - - Serial.println(); - } else if (input == 'e') { - Serial.print("Erasing Flash chip ... "); - flash.chipErase(); - while(flash.busy()); - Serial.println("DONE"); - } else if (input == 'i') { - Serial.print("DeviceID: "); - Serial.println(flash.readDeviceId(), HEX); - } else if (input >= 48 && input <= 57) { //0-9 - Serial.print("\nWriteByte("); - Serial.print(input); - Serial.print(")"); - flash.writeByte(input-48, (millis()%2) ? 0xaa : 0xbb); - } - } - - // Periodically blink the onboard LED while listening for serial commands - if ((int)(millis()/500) > lastPeriod) { - lastPeriod++; - pinMode(LED, OUTPUT); - digitalWrite(LED, lastPeriod%2); - } -} - -void Blink(byte PIN, int DELAY_MS, byte loops) -{ - pinMode(PIN, OUTPUT); - while (loops--) { - digitalWrite(PIN,HIGH); - delay(DELAY_MS); - digitalWrite(PIN,LOW); - delay(DELAY_MS); - } -} \ No newline at end of file diff --git a/lib/MySensors/drivers/SPIFlash/keywords.txt b/lib/MySensors/drivers/SPIFlash/keywords.txt deleted file mode 100644 index 652da982..00000000 --- a/lib/MySensors/drivers/SPIFlash/keywords.txt +++ /dev/null @@ -1,18 +0,0 @@ -SPIFlash KEYWORD1 -initialize KEYWORD2 -command KEYWORD2 -readStatus KEYWORD2 -readByte KEYWORD2 -readBytes KEYWORD2 -writeByte KEYWORD2 -writeBytes KEYWORD2 -flashBusy KEYWORD2 -chipErase KEYWORD2 -blockErase4K KEYWORD2 -blockErase32K KEYWORD2 -readDeviceId KEYWORD2 -readUniqueId KEYWORD2 -UNIQUEID KEYWORD2 -sleep KEYWORD2 -wakeup KEYWORD2 -end KEYWORD2 \ No newline at end of file diff --git a/lib/MySensors/drivers/TinyGSM/LICENSE b/lib/MySensors/drivers/TinyGSM/LICENSE deleted file mode 100644 index 65c5ca88..00000000 --- a/lib/MySensors/drivers/TinyGSM/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmClient.h b/lib/MySensors/drivers/TinyGSM/TinyGsmClient.h deleted file mode 100644 index 8badab17..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmClient.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * file TinyGsmClient.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmClient_h -#define TinyGsmClient_h - -#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM868) || defined(TINY_GSM_MODEM_U201) || defined(TINY_GSM_MODEM_ESP8266) -#define TINY_GSM_MODEM_HAS_SSL -#endif - -#if defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868) || defined(TINY_GSM_MODEM_A7) -#define TINY_GSM_MODEM_HAS_GPS -#endif - -#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900) -#define TINY_GSM_MODEM_HAS_GPRS -#include "TinyGsmClientSIM800.h" -typedef TinyGsmSim800 TinyGsm; -typedef TinyGsmSim800::GsmClient TinyGsmClient; -typedef TinyGsmSim800::GsmClientSecure TinyGsmClientSecure; - -#elif defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868) -#define TINY_GSM_MODEM_HAS_GPRS -#include "TinyGsmClientSIM808.h" -typedef TinyGsmSim808 TinyGsm; -typedef TinyGsmSim808::GsmClient TinyGsmClient; -typedef TinyGsmSim808::GsmClientSecure TinyGsmClientSecure; - -#elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7) -#define TINY_GSM_MODEM_HAS_GPRS -#include "TinyGsmClientA6.h" -typedef TinyGsm::GsmClient TinyGsmClient; - -#elif defined(TINY_GSM_MODEM_M590) -#define TINY_GSM_MODEM_HAS_GPRS -#include "TinyGsmClientM590.h" -typedef TinyGsm::GsmClient TinyGsmClient; - -#elif defined(TINY_GSM_MODEM_U201) -#define TINY_GSM_MODEM_HAS_GPRS -#include "TinyGsmClientU201.h" -typedef TinyGsmU201 TinyGsm; -typedef TinyGsmU201::GsmClient TinyGsmClient; -typedef TinyGsmU201::GsmClientSecure TinyGsmClientSecure; - -#elif defined(TINY_GSM_MODEM_ESP8266) -#define TINY_GSM_MODEM_HAS_WIFI -#include "TinyGsmClientESP8266.h" -typedef TinyGsm::GsmClient TinyGsmClient; -typedef TinyGsm::GsmClientSecure TinyGsmClientSecure; - -#elif defined(TINY_GSM_MODEM_XBEE) -#define TINY_GSM_MODEM_HAS_GPRS -#define TINY_GSM_MODEM_HAS_WIFI -#include "TinyGsmClientXBee.h" -typedef TinyGsm::GsmClient TinyGsmClient; - -#else -#error "Please define GSM modem model" -#endif - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmClientA6.h b/lib/MySensors/drivers/TinyGSM/TinyGsmClientA6.h deleted file mode 100644 index 7630378d..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmClientA6.h +++ /dev/null @@ -1,843 +0,0 @@ -/** - * file TinyGsmClientA6.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmClientA6_h -#define TinyGsmClientA6_h - -//#define TINY_GSM_DEBUG Serial - -#if !defined(TINY_GSM_RX_BUFFER) -#define TINY_GSM_RX_BUFFER 256 -#endif - -#define TINY_GSM_MUX_COUNT 8 - -#include "TinyGsmCommon.h" - -#define GSM_NL "\r\n" -static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; -static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; - -enum SimStatus { - SIM_ERROR = 0, - SIM_READY = 1, - SIM_LOCKED = 2, -}; - -enum RegStatus { - REG_UNREGISTERED = 0, - REG_SEARCHING = 2, - REG_DENIED = 3, - REG_OK_HOME = 1, - REG_OK_ROAMING = 5, - REG_UNKNOWN = 4, -}; - - -class TinyGsm -{ - -public: - - class GsmClient : public Client - { - friend class TinyGsm; - typedef TinyGsmFifo RxFifo; - - public: - GsmClient() {} - - GsmClient(TinyGsm& modem) - { - init(&modem); - } - - bool init(TinyGsm* modem) - { - this->at = modem; - this->mux = -1; - sock_connected = false; - - return true; - } - - public: - virtual int connect(const char *host, uint16_t port) - { - stop(); - TINY_GSM_YIELD(); - rx.clear(); - uint8_t newMux = -1; - sock_connected = at->modemConnect(host, port, &newMux); - if (sock_connected) { - mux = newMux; - at->sockets[mux] = this; - } - return sock_connected; - } - - virtual int connect(IPAddress ip, uint16_t port) - { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return connect(host.c_str(), port); - } - - virtual void stop() - { - TINY_GSM_YIELD(); - at->sendAT(GF("+CIPCLOSE="), mux); - sock_connected = false; - at->waitResponse(); - rx.clear(); - } - - virtual size_t write(const uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - //at->maintain(); - return at->modemSend(buf, size, mux); - } - - virtual size_t write(uint8_t c) - { - return write(&c, 1); - } - - virtual int available() - { - TINY_GSM_YIELD(); - if (!rx.size() && sock_connected) { - at->maintain(); - } - return rx.size(); - } - - virtual int read(uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - size_t cnt = 0; - while (cnt < size) { - size_t chunk = TinyGsmMin(size-cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } - // TODO: Read directly into user buffer? - if (!rx.size() && sock_connected) { - at->maintain(); - //break; - } - } - return cnt; - } - - virtual int read() - { - uint8_t c; - if (read(&c, 1) == 1) { - return c; - } - return -1; - } - - virtual int peek() - { - return -1; //TODO - } - virtual void flush() - { - at->stream.flush(); - } - - virtual uint8_t connected() - { - if (available()) { - return true; - } - return sock_connected; - } - virtual operator bool() - { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - private: - TinyGsm* at; - uint8_t mux; - bool sock_connected; - RxFifo rx; - }; - -public: - - explicit TinyGsm(Stream& stream) - : stream(stream) - { - memset(sockets, 0, sizeof(sockets)); - } - - /* - * Basic functions - */ - bool begin() - { - return init(); - } - - bool init() - { - if (!testAT()) { - return false; - } - sendAT(GF("&FZE0")); // Factory + Reset + Echo Off - if (waitResponse() != 1) { - return false; - } - sendAT(GF("+CMEE=0")); - waitResponse(); - - sendAT(GF("+CMER=3,0,0,2")); - waitResponse(); - - getSimStatus(); - return true; - } - - void setBaud(unsigned long baud) - { - sendAT(GF("+IPR="), baud); - } - - bool testAT(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("")); - if (waitResponse(200) == 1) { - delay(100); - return true; - } - delay(100); - } - return false; - } - - void maintain() - { - waitResponse(10, NULL, NULL); - } - - bool factoryDefault() - { - sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write - waitResponse(); - sendAT(GF("&W")); // Write configuration - return waitResponse() == 1; - } - - String getModemInfo() - { - sendAT(GF("I")); - String res; - if (waitResponse(1000L, res) != 1) { - return ""; - } - res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, " "); - res.trim(); - return res; - } - - bool hasSSL() - { - return false; - } - - /* - * Power functions - */ - - bool restart() - { - if (!testAT()) { - return false; - } - sendAT(GF("+RST=1")); - delay(3000); - return init(); - } - - bool poweroff() - { - sendAT(GF("+CPOF")); - return waitResponse() == 1; - } - - bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; - - /* - * SIM card functions - */ - - bool simUnlock(const char *pin) - { - sendAT(GF("+CPIN=\""), pin, GF("\"")); - return waitResponse() == 1; - } - - String getSimCCID() - { - sendAT(GF("+CCID")); - if (waitResponse(GF(GSM_NL "+SCID: SIM Card ID:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - String getIMEI() - { - sendAT(GF("+GSN")); - if (waitResponse(GF(GSM_NL)) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - SimStatus getSimStatus(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("+CPIN?")); - if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) { - delay(1000); - continue; - } - int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK")); - waitResponse(); - switch (status) { - case 2: - case 3: - return SIM_LOCKED; - case 1: - return SIM_READY; - default: - return SIM_ERROR; - } - } - return SIM_ERROR; - } - - RegStatus getRegistrationStatus() - { - sendAT(GF("+CREG?")); - if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { - return REG_UNKNOWN; - } - streamSkipUntil(','); // Skip format (0) - int status = stream.readStringUntil('\n').toInt(); - waitResponse(); - return (RegStatus)status; - } - - String getOperator() - { - sendAT(GF("+COPS=3,0")); // Set format - waitResponse(); - - sendAT(GF("+COPS?")); - if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { - return ""; - } - streamSkipUntil('"'); // Skip mode and format - String res = stream.readStringUntil('"'); - waitResponse(); - return res; - } - - /* - * Generic network functions - */ - - int getSignalQuality() - { - sendAT(GF("+CSQ")); - if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { - return 99; - } - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - bool isNetworkConnected() - { - RegStatus s = getRegistrationStatus(); - return (s == REG_OK_HOME || s == REG_OK_ROAMING); - } - - bool waitForNetwork(unsigned long timeout = 60000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - if (isNetworkConnected()) { - return true; - } - delay(250); - } - return false; - } - - /* - * GPRS functions - */ - bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) - { - gprsDisconnect(); - - sendAT(GF("+CGATT=1")); - if (waitResponse(60000L) != 1) { - return false; - } - - // TODO: wait AT+CGATT? - - sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); - waitResponse(); - - if (!user) { - user = ""; - } - if (!pwd) { - pwd = ""; - } - sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); - if (waitResponse(60000L) != 1) { - return false; - } - - sendAT(GF("+CGACT=1,1")); - waitResponse(60000L); - - sendAT(GF("+CIPMUX=1")); - if (waitResponse() != 1) { - return false; - } - - return true; - } - - bool gprsDisconnect() - { - // Shut the TCP/IP connection - sendAT(GF("+CIPSHUT")); - if (waitResponse(60000L) != 1) { - return false; - } - - for (int i = 0; i<3; i++) { - sendAT(GF("+CGATT=0")); - if (waitResponse(5000L) == 1) { - return true; - } - } - - return false; - } - - bool isGprsConnected() - { - sendAT(GF("+CGATT?")); - if (waitResponse(GF(GSM_NL "+CGATT:")) != 1) { - return false; - } - int res = stream.readStringUntil('\n').toInt(); - waitResponse(); - return (res == 1); - } - - String getLocalIP() - { - sendAT(GF("+CIFSR")); - String res; - if (waitResponse(10000L, res) != 1) { - return ""; - } - res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, ""); - res.trim(); - return res; - } - - IPAddress localIP() - { - return TinyGsmIpFromString(getLocalIP()); - } - - /* - * Phone Call functions - */ - - bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; - - bool callAnswer() - { - sendAT(GF("A")); - return waitResponse() == 1; - } - - // Returns true on pick-up, false on error/busy - bool callNumber(const String& number) - { - if (number == GF("last")) { - sendAT(GF("DLST")); - } else { - sendAT(GF("D\""), number, "\";"); - } - - if (waitResponse(5000L) != 1) { - return false; - } - - if (waitResponse(60000L, - GF(GSM_NL "+CIEV: \"CALL\",1"), - GF(GSM_NL "+CIEV: \"CALL\",0"), - GFP(GSM_ERROR)) != 1) { - return false; - } - - int rsp = waitResponse(60000L, - GF(GSM_NL "+CIEV: \"SOUNDER\",0"), - GF(GSM_NL "+CIEV: \"CALL\",0")); - - int rsp2 = waitResponse(300L, GF(GSM_NL "BUSY" GSM_NL), GF(GSM_NL "NO ANSWER" GSM_NL)); - - return rsp == 1 && rsp2 == 0; - } - - bool callHangup() - { - sendAT(GF("H")); - return waitResponse() == 1; - } - - // 0-9,*,#,A,B,C,D - bool dtmfSend(char cmd, unsigned duration_ms = 100) - { - duration_ms = constrain(duration_ms, 100, 1000); - - // The duration parameter is not working, so we simulate it using delay.. - // TODO: Maybe there's another way... - - //sendAT(GF("+VTD="), duration_ms / 100); - //waitResponse(); - - sendAT(GF("+VTS="), cmd); - if (waitResponse(10000L) == 1) { - delay(duration_ms); - return true; - } - return false; - } - - /* - * Audio functions - */ - - bool audioSetHeadphones() - { - sendAT(GF("+SNFS=0")); - return waitResponse() == 1; - } - - bool audioSetSpeaker() - { - sendAT(GF("+SNFS=1")); - return waitResponse() == 1; - } - - bool audioMuteMic(bool mute) - { - sendAT(GF("+CMUT="), mute); - return waitResponse() == 1; - } - - /* - * Messaging functions - */ - - String sendUSSD(const String& code) - { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CUSD=1,\""), code, GF("\",15")); - if (waitResponse(10000L) != 1) { - return ""; - } - if (waitResponse(GF(GSM_NL "+CUSD:")) != 1) { - return ""; - } - stream.readStringUntil('"'); - String hex = stream.readStringUntil('"'); - stream.readStringUntil(','); - int dcs = stream.readStringUntil('\n').toInt(); - - if (dcs == 15) { - return TinyGsmDecodeHex7bit(hex); - } else if (dcs == 72) { - return TinyGsmDecodeHex16bit(hex); - } else { - return hex; - } - } - - bool sendSMS(const String& number, const String& text) - { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - stream.print(text); - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - - - /* - * Location functions - */ - - String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * Battery functions - */ - - uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; - - int getBattPercent() - { - sendAT(GF("+CBC?")); - if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { - return false; - } - stream.readStringUntil(','); - int res = stream.readStringUntil('\n').toInt(); - waitResponse(); - return res; - } - -protected: - - bool modemConnect(const char* host, uint16_t port, uint8_t* mux) - { - sendAT(GF("+CIPSTART="), GF("\"TCP"), GF("\",\""), host, GF("\","), port); - - if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) { - return false; - } - int newMux = stream.readStringUntil('\n').toInt(); - - int rsp = waitResponse(75000L, - GF("CONNECT OK" GSM_NL), - GF("CONNECT FAIL" GSM_NL), - GF("ALREADY CONNECT" GSM_NL)); - if (waitResponse() != 1) { - return false; - } - *mux = newMux; - - return (1 == rsp); - } - - int modemSend(const void* buff, size_t len, uint8_t mux) - { - sendAT(GF("+CIPSEND="), mux, ',', len); - if (waitResponse(2000L, GF(GSM_NL ">")) != 1) { - return 0; - } - stream.write((uint8_t*)buff, len); - stream.flush(); - if (waitResponse(10000L, GFP(GSM_OK), GF(GSM_NL "FAIL")) != 1) { - return 0; - } - return len; - } - - bool modemGetConnected(uint8_t mux) - { - sendAT(GF("+CIPSTATUS")); //TODO mux? - int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), - GF(",\"INITIAL\"")); - waitResponse(); - return 1 == res; - } - -public: - - /* Utilities */ - - template - void streamWrite(T last) - { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) - { - stream.print(head); - streamWrite(tail...); - } - - bool streamSkipUntil(char c) //TODO: timeout - { - while (true) { - while (!stream.available()) { - TINY_GSM_YIELD(); - } - if (stream.read() == c) { - return true; - } - } - return false; - } - - template - void sendAT(Args... cmd) - { - streamWrite("AT", cmd..., GSM_NL); - stream.flush(); - TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); - } - - // TODO: Optimize this! - uint8_t waitResponse(uint32_t timeout, String& data, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - /*String r1s(r1); r1s.trim(); - String r2s(r2); r2s.trim(); - String r3s(r3); r3s.trim(); - String r4s(r4); r4s.trim(); - String r5s(r5); r5s.trim(); - DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ - data.reserve(64); - int index = 0; - unsigned long startMillis = millis(); - do { - TINY_GSM_YIELD(); - while (stream.available() > 0) { - int a = stream.read(); - if (a <= 0) { - continue; // Skip 0x00 bytes, just in case - } - data += (char)a; - if (r1 && data.endsWith(r1)) { - index = 1; - goto finish; - } else if (r2 && data.endsWith(r2)) { - index = 2; - goto finish; - } else if (r3 && data.endsWith(r3)) { - index = 3; - goto finish; - } else if (r4 && data.endsWith(r4)) { - index = 4; - goto finish; - } else if (r5 && data.endsWith(r5)) { - index = 5; - goto finish; - } else if (data.endsWith(GF("+CIPRCV:"))) { - int mux = stream.readStringUntil(',').toInt(); - int len = stream.readStringUntil(',').toInt(); - int len_orig = len; - if (len > sockets[mux]->rx.free()) { - DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); - } else { - DBG("### Got: ", len, "->", sockets[mux]->rx.free()); - } - while (len--) { - while (!stream.available()) { - TINY_GSM_YIELD(); - } - sockets[mux]->rx.put(stream.read()); - } - if (len_orig > sockets[mux]->available()) { // TODO - DBG("### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig); - } - data = ""; - } else if (data.endsWith(GF("+TCPCLOSED:"))) { - int mux = stream.readStringUntil('\n').toInt(); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { - sockets[mux]->sock_connected = false; - } - data = ""; - DBG("### Closed: ", mux); - } - } - } while (millis() - startMillis < timeout); -finish: - if (!index) { - data.trim(); - if (data.length()) { - DBG("### Unhandled:", data); - } - data = ""; - } - return index; - } - - uint8_t waitResponse(uint32_t timeout, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - String data; - return waitResponse(timeout, data, r1, r2, r3, r4, r5); - } - - uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - return waitResponse(1000, r1, r2, r3, r4, r5); - } - -public: - Stream& stream; - -protected: - GsmClient* sockets[TINY_GSM_MUX_COUNT]; -}; - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmClientESP8266.h b/lib/MySensors/drivers/TinyGSM/TinyGsmClientESP8266.h deleted file mode 100644 index 76d88eaf..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmClientESP8266.h +++ /dev/null @@ -1,591 +0,0 @@ -/** - * file TinyGsmClientESP8266.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmClientESP8266_h -#define TinyGsmClientESP8266_h - -//#define TINY_GSM_DEBUG Serial - -#if !defined(TINY_GSM_RX_BUFFER) -#define TINY_GSM_RX_BUFFER 512 -#endif - -#define TINY_GSM_MUX_COUNT 5 - -#include "TinyGsmCommon.h" - -#define GSM_NL "\r\n" -static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; -static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; -static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120; - -class TinyGsm -{ - -public: - - class GsmClient : public Client - { - friend class TinyGsm; - typedef TinyGsmFifo RxFifo; - - public: - GsmClient() {} - - GsmClient(TinyGsm& modem, uint8_t mux = 1) - { - init(&modem, mux); - } - - bool init(TinyGsm* modem, uint8_t mux = 1) - { - this->at = modem; - this->mux = mux; - sock_connected = false; - - at->sockets[mux] = this; - - return true; - } - - public: - virtual int connect(const char *host, uint16_t port) - { - stop(); - TINY_GSM_YIELD(); - rx.clear(); - sock_connected = at->modemConnect(host, port, mux); - return sock_connected; - } - - virtual int connect(IPAddress ip, uint16_t port) - { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return connect(host.c_str(), port); - } - - virtual void stop() - { - TINY_GSM_YIELD(); - at->sendAT(GF("+CIPCLOSE="), mux); - sock_connected = false; - at->waitResponse(); - rx.clear(); - } - - virtual size_t write(const uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - //at->maintain(); - return at->modemSend(buf, size, mux); - } - - virtual size_t write(uint8_t c) - { - return write(&c, 1); - } - - virtual int available() - { - TINY_GSM_YIELD(); - if (!rx.size() && sock_connected) { - at->maintain(); - } - return rx.size(); - } - - virtual int read(uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - size_t cnt = 0; - while (cnt < size) { - size_t chunk = TinyGsmMin(size-cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } - // TODO: Read directly into user buffer? - if (!rx.size() && sock_connected) { - at->maintain(); - //break; - } - } - return cnt; - } - - virtual int read() - { - uint8_t c; - if (read(&c, 1) == 1) { - return c; - } - return -1; - } - - virtual int peek() - { - return -1; //TODO - } - virtual void flush() - { - at->stream.flush(); - } - - virtual uint8_t connected() - { - if (available()) { - return true; - } - return sock_connected; - } - virtual operator bool() - { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - private: - TinyGsm* at; - uint8_t mux; - bool sock_connected; - RxFifo rx; - }; - - class GsmClientSecure : public GsmClient - { - public: - GsmClientSecure() {} - - GsmClientSecure(TinyGsm& modem, uint8_t mux = 1) - : GsmClient(modem, mux) - {} - - public: - virtual int connect(const char *host, uint16_t port) - { - stop(); - TINY_GSM_YIELD(); - rx.clear(); - sock_connected = at->modemConnect(host, port, mux, true); - return sock_connected; - } - }; - -public: - - explicit TinyGsm(Stream& stream) - : stream(stream) - { - memset(sockets, 0, sizeof(sockets)); - } - - /* - * Basic functions - */ - bool begin() - { - return init(); - } - - bool init() - { - if (!testAT()) { - return false; - } - sendAT(GF("E0")); // Echo Off - if (waitResponse() != 1) { - return false; - } - return true; - } - - void setBaud(unsigned long baud) - { - sendAT(GF("+IPR="), baud); - } - - bool testAT(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("")); - if (waitResponse(200) == 1) { - delay(100); - return true; - } - delay(100); - } - return false; - } - - void maintain() - { - waitResponse(10, NULL, NULL); - } - - bool factoryDefault() - { - sendAT(GF("+RESTORE")); - return waitResponse() == 1; - } - - String getModemInfo() - { - sendAT(GF("+GMR")); - String res; - if (waitResponse(1000L, res) != 1) { - return ""; - } - res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, " "); - res.trim(); - return res; - } - - bool hasSSL() - { - return true; - } - - /* - * Power functions - */ - - bool restart() - { - if (!testAT()) { - return false; - } - sendAT(GF("+RST")); - if (waitResponse(10000L) != 1) { - return false; - } - if (waitResponse(10000L, GF(GSM_NL "ready" GSM_NL)) != 1) { - return false; - } - delay(500); - return init(); - } - - - /* - * Generic network functions - */ - - int getSignalQuality() - { - sendAT(GF("+CWJAP_CUR?")); - int res1 = waitResponse(GF("No AP"), GF("+CWJAP_CUR:")); - if (res1 != 2) { - waitResponse(); - return 0; - } - streamSkipUntil(','); // Skip SSID - streamSkipUntil(','); // Skip BSSID/MAC address - streamSkipUntil(','); // Skip Chanel number - int res2 = stream.parseInt(); // Read RSSI - waitResponse(); // Returns an OK after the value - return res2; - } - - bool isNetworkConnected() - { - sendAT(GF("+CIPSTATUS")); - int res1 = waitResponse(3000, GF("STATUS:")); - int res2 = 0; - if (res1 == 1) { - res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); - } - // status of ESP8266 station interface - // 2 : ESP8266 station connected to an AP and has obtained IP - // 3 : ESP8266 station created a TCP or UDP transmission - // 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected) - // 5 : ESP8266 station did NOT connect to an AP - waitResponse(); // Returns an OK after the status - if (res2 == 2 || res2 == 3 || res2 == 4) { - return true; - } else { - return false; - } - } - - bool waitForNetwork(unsigned long timeout = 60000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("+CIPSTATUS")); - int res1 = waitResponse(3000, GF("busy p..."), GF("STATUS:")); - if (res1 == 2) { - int res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); - if (res2 == 2 || res2 == 3 || res2 == 4) { - waitResponse(); - return true; - } - } - delay(250); - } - return false; - } - - /* - * WiFi functions - */ - bool networkConnect(const char* ssid, const char* pwd) - { - - sendAT(GF("+CIPMUX=1")); - if (waitResponse() != 1) { - return false; - } - - sendAT(GF("+CWMODE_CUR=1")); - if (waitResponse() != 1) { - return false; - } - - sendAT(GF("+CWJAP_CUR=\""), ssid, GF("\",\""), pwd, GF("\"")); - if (waitResponse(30000L, GFP(GSM_OK), GF(GSM_NL "FAIL" GSM_NL)) != 1) { - return false; - } - - return true; - } - - bool networkDisconnect() - { - sendAT(GF("+CWQAP")); - bool retVal = waitResponse(10000L) == 1; - waitResponse(GF("WIFI DISCONNECT")); - return retVal; - } - - String getLocalIP() - { - sendAT(GF("+CIPSTA_CUR??")); - int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:")); - if (res1 != 2) { - return ""; - } - String res2 = stream.readStringUntil('"'); - waitResponse(); - return res2; - } - - IPAddress localIP() - { - return TinyGsmIpFromString(getLocalIP()); - } - -protected: - - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) - { - if (ssl) { - sendAT(GF("+CIPSSLSIZE=4096")); - waitResponse(); - } - sendAT(GF("+CIPSTART="), mux, ',', ssl ? GF("\"SSL") : GF("\"TCP"), GF("\",\""), host, GF("\","), - port, GF(","), TINY_GSM_TCP_KEEP_ALIVE); - // TODO: Check mux - int rsp = waitResponse(75000L, - GFP(GSM_OK), - GFP(GSM_ERROR), - GF("ALREADY CONNECT")); - // if (rsp == 3) waitResponse(); // May return "ERROR" after the "ALREADY CONNECT" - return (1 == rsp); - } - - int modemSend(const void* buff, size_t len, uint8_t mux) - { - sendAT(GF("+CIPSEND="), mux, ',', len); - if (waitResponse(GF(">")) != 1) { - return 0; - } - stream.write((uint8_t*)buff, len); - stream.flush(); - if (waitResponse(10000L, GF(GSM_NL "SEND OK" GSM_NL)) != 1) { - return 0; - } - return len; - } - - bool modemGetConnected(uint8_t mux) - { - // TODO: re-check this - sendAT(GF("+CIPSTATUS="), mux); - int res1 = waitResponse(3000, GF("STATUS:")); - int res2; - if (res1 == 1) { - res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5")); - } - // status of ESP8266 station interface - // 2 : ESP8266 station connected to an AP and has obtained IP - // 3 : ESP8266 station created a TCP or UDP transmission - // 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected) - // 5 : ESP8266 station did NOT connect to an AP - waitResponse(); // Returns an OK after the status - if (res2 == 2 || res2 == 3 || res2 == 4) { - return true; - } else { - return false; - } - } - -public: - - /* Utilities */ - - template - void streamWrite(T last) - { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) - { - stream.print(head); - streamWrite(tail...); - } - - bool streamSkipUntil(char c) //TODO: timeout - { - while (true) { - while (!stream.available()) { - TINY_GSM_YIELD(); - } - if (stream.read() == c) { - return true; - } - } - return false; - } - - template - void sendAT(Args... cmd) - { - streamWrite("AT", cmd..., GSM_NL); - stream.flush(); - TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); - } - - // TODO: Optimize this! - uint8_t waitResponse(uint32_t timeout, String& data, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - /*String r1s(r1); r1s.trim(); - String r2s(r2); r2s.trim(); - String r3s(r3); r3s.trim(); - String r4s(r4); r4s.trim(); - String r5s(r5); r5s.trim(); - DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ - data.reserve(64); - int index = 0; - unsigned long startMillis = millis(); - do { - TINY_GSM_YIELD(); - while (stream.available() > 0) { - int a = stream.read(); - if (a <= 0) { - continue; // Skip 0x00 bytes, just in case - } - data += (char)a; - if (r1 && data.endsWith(r1)) { - index = 1; - goto finish; - } else if (r2 && data.endsWith(r2)) { - index = 2; - goto finish; - } else if (r3 && data.endsWith(r3)) { - index = 3; - goto finish; - } else if (r4 && data.endsWith(r4)) { - index = 4; - goto finish; - } else if (r5 && data.endsWith(r5)) { - index = 5; - goto finish; - } else if (data.endsWith(GF(GSM_NL "+IPD,"))) { - int mux = stream.readStringUntil(',').toInt(); - int len = stream.readStringUntil(':').toInt(); - int len_orig = len; - if (len > sockets[mux]->rx.free()) { - DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); - } else { - DBG("### Got: ", len, "->", sockets[mux]->rx.free()); - } - while (len--) { - while (!stream.available()) { - TINY_GSM_YIELD(); - } - sockets[mux]->rx.put(stream.read()); - } - if (len_orig > sockets[mux]->available()) { // TODO - DBG("### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig); - } - data = ""; - } else if (data.endsWith(GF("CLOSED"))) { - int muxStart = max(0,data.lastIndexOf(GSM_NL, data.length()-8)); - int coma = data.indexOf(',', muxStart); - int mux = data.substring(muxStart, coma).toInt(); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { - sockets[mux]->sock_connected = false; - } - data = ""; - DBG("### Closed: ", mux); - } - } - } while (millis() - startMillis < timeout); -finish: - if (!index) { - data.trim(); - if (data.length()) { - DBG("### Unhandled:", data); - } - data = ""; - } - return index; - } - - uint8_t waitResponse(uint32_t timeout, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - String data; - return waitResponse(timeout, data, r1, r2, r3, r4, r5); - } - - uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - return waitResponse(1000, r1, r2, r3, r4, r5); - } - -public: - Stream& stream; - -protected: - GsmClient* sockets[TINY_GSM_MUX_COUNT]; -}; - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmClientM590.h b/lib/MySensors/drivers/TinyGSM/TinyGsmClientM590.h deleted file mode 100644 index 5c6288fb..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmClientM590.h +++ /dev/null @@ -1,781 +0,0 @@ -/** - * file TinyGsmClientM590.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmClientM590_h -#define TinyGsmClientM590_h - -//#define TINY_GSM_DEBUG Serial - -#if !defined(TINY_GSM_RX_BUFFER) -#define TINY_GSM_RX_BUFFER 256 -#endif - -#define TINY_GSM_MUX_COUNT 2 - -#include "TinyGsmCommon.h" - -#define GSM_NL "\r\n" -static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; -static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; - -enum SimStatus { - SIM_ERROR = 0, - SIM_READY = 1, - SIM_LOCKED = 2, -}; - -enum RegStatus { - REG_UNREGISTERED = 0, - REG_SEARCHING = 3, - REG_DENIED = 2, - REG_OK_HOME = 1, - REG_OK_ROAMING = 5, - REG_UNKNOWN = 4, -}; - - -class TinyGsm -{ - -public: - - class GsmClient : public Client - { - friend class TinyGsm; - typedef TinyGsmFifo RxFifo; - - public: - GsmClient() {} - - GsmClient(TinyGsm& modem, uint8_t mux = 1) - { - init(&modem, mux); - } - - bool init(TinyGsm* modem, uint8_t mux = 1) - { - this->at = modem; - this->mux = mux; - sock_connected = false; - - at->sockets[mux] = this; - - return true; - } - - public: - virtual int connect(const char *host, uint16_t port) - { - stop(); - TINY_GSM_YIELD(); - rx.clear(); - sock_connected = at->modemConnect(host, port, mux); - return sock_connected; - } - - virtual int connect(IPAddress ip, uint16_t port) - { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return connect(host.c_str(), port); - } - - virtual void stop() - { - TINY_GSM_YIELD(); - at->sendAT(GF("+TCPCLOSE="), mux); - sock_connected = false; - at->waitResponse(); - rx.clear(); - } - - virtual size_t write(const uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - //at->maintain(); - return at->modemSend(buf, size, mux); - } - - virtual size_t write(uint8_t c) - { - return write(&c, 1); - } - - virtual int available() - { - TINY_GSM_YIELD(); - if (!rx.size() && sock_connected) { - at->maintain(); - } - return rx.size(); - } - - virtual int read(uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - size_t cnt = 0; - while (cnt < size) { - size_t chunk = TinyGsmMin(size-cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } - // TODO: Read directly into user buffer? - if (!rx.size() && sock_connected) { - at->maintain(); - //break; - } - } - return cnt; - } - - virtual int read() - { - uint8_t c; - if (read(&c, 1) == 1) { - return c; - } - return -1; - } - - virtual int peek() - { - return -1; //TODO - } - virtual void flush() - { - at->stream.flush(); - } - - virtual uint8_t connected() - { - if (available()) { - return true; - } - return sock_connected; - } - virtual operator bool() - { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - private: - TinyGsm* at; - uint8_t mux; - bool sock_connected; - RxFifo rx; - }; - -public: - - explicit TinyGsm(Stream& stream) - : stream(stream) - { - memset(sockets, 0, sizeof(sockets)); - } - - /* - * Basic functions - */ - bool begin() - { - return init(); - } - - bool init() - { - if (!testAT()) { - return false; - } - sendAT(GF("&FZE0")); // Factory + Reset + Echo Off - if (waitResponse() != 1) { - return false; - } -#ifdef TINY_GSM_DEBUG - sendAT(GF("+CMEE=2")); - waitResponse(); -#endif - - getSimStatus(); - return true; - } - - void setBaud(unsigned long baud) - { - sendAT(GF("+IPR="), baud); - } - - bool testAT(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("")); - if (waitResponse(200) == 1) { - delay(100); - return true; - } - delay(100); - } - return false; - } - - void maintain() - { - //while (stream.available()) { - waitResponse(10, NULL, NULL); - //} - } - - bool factoryDefault() - { - sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write - waitResponse(); - sendAT(GF("+ICF=3,1")); // 8 data 0 parity 1 stop - waitResponse(); - sendAT(GF("+ENPWRSAVE=0")); // Disable PWR save - waitResponse(); - sendAT(GF("+XISP=0")); // Use internal stack - waitResponse(); - sendAT(GF("&W")); // Write configuration - return waitResponse() == 1; - } - - String getModemInfo() - { - sendAT(GF("I")); - String res; - if (waitResponse(1000L, res) != 1) { - return ""; - } - res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, " "); - res.trim(); - return res; - } - - bool hasSSL() - { - return false; - } - - /* - * Power functions - */ - - bool restart() - { - if (!testAT()) { - return false; - } - sendAT(GF("+CFUN=15")); - if (waitResponse(10000L) != 1) { - return false; - } - //MODEM:STARTUP - waitResponse(60000L, GF(GSM_NL "+PBREADY" GSM_NL)); - return init(); - } - - bool poweroff() - { - sendAT(GF("+CPWROFF")); - return waitResponse(3000L) == 1; - } - - bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool sleepEnable(bool enable = true) - { - sendAT(GF("+ENPWRSAVE="), enable); - return waitResponse() == 1; - } - - /* - * SIM card functions - */ - - bool simUnlock(const char *pin) - { - sendAT(GF("+CPIN=\""), pin, GF("\"")); - return waitResponse() == 1; - } - - String getSimCCID() - { - sendAT(GF("+CCID")); - if (waitResponse(GF(GSM_NL "+CCID:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - String getIMEI() - { - sendAT(GF("+GSN")); - if (waitResponse(GF(GSM_NL)) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - SimStatus getSimStatus(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("+CPIN?")); - if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) { - delay(1000); - continue; - } - int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK")); - waitResponse(); - switch (status) { - case 2: - case 3: - return SIM_LOCKED; - case 1: - return SIM_READY; - default: - return SIM_ERROR; - } - } - return SIM_ERROR; - } - - RegStatus getRegistrationStatus() - { - sendAT(GF("+CREG?")); - if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { - return REG_UNKNOWN; - } - streamSkipUntil(','); // Skip format (0) - int status = stream.readStringUntil('\n').toInt(); - waitResponse(); - return (RegStatus)status; - } - - String getOperator() - { - sendAT(GF("+COPS?")); - if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { - return ""; - } - streamSkipUntil('"'); // Skip mode and format - String res = stream.readStringUntil('"'); - waitResponse(); - return res; - } - - /* - * Generic network functions - */ - - int getSignalQuality() - { - sendAT(GF("+CSQ")); - if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { - return 99; - } - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - bool isNetworkConnected() - { - RegStatus s = getRegistrationStatus(); - return (s == REG_OK_HOME || s == REG_OK_ROAMING); - } - - bool waitForNetwork(unsigned long timeout = 60000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - if (isNetworkConnected()) { - return true; - } - delay(250); - } - return false; - } - - /* - * GPRS functions - */ - bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) - { - gprsDisconnect(); - - sendAT(GF("+XISP=0")); - waitResponse(); - - sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); - waitResponse(); - - if (!user) { - user = ""; - } - if (!pwd) { - pwd = ""; - } - sendAT(GF("+XGAUTH=1,1,\""), user, GF("\",\""), pwd, GF("\"")); - waitResponse(); - - sendAT(GF("+XIIC=1")); - waitResponse(); - - const unsigned long timeout = 60000L; - for (unsigned long start = millis(); millis() - start < timeout; ) { - if (isGprsConnected()) { - //goto set_dns; // TODO - return true; - } - delay(500); - } - return false; - -set_dns: - sendAT(GF("+DNSSERVER=1,8.8.8.8")); - waitResponse(); - - sendAT(GF("+DNSSERVER=2,8.8.4.4")); - waitResponse(); - - return true; - } - - bool gprsDisconnect() - { - // TODO: There is no command in AT command set - // XIIC=0 does not work - return true; - } - - bool isGprsConnected() - { - sendAT(GF("+XIIC?")); - if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) { - return false; - } - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res == 1; - } - - String getLocalIP() - { - sendAT(GF("+XIIC?")); - if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) { - return ""; - } - stream.readStringUntil(','); - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - IPAddress localIP() - { - return TinyGsmIpFromString(getLocalIP()); - } - - /* - * Phone Call functions - */ - - bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE; - - bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE; - - bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE; - - bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * Messaging functions - */ - - String sendUSSD(const String& code) - { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("D"), code); - if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { - return ""; - } - stream.readStringUntil('"'); - String hex = stream.readStringUntil('"'); - stream.readStringUntil(','); - int dcs = stream.readStringUntil('\n').toInt(); - - if (waitResponse() != 1) { - return ""; - } - - if (dcs == 15) { - return TinyGsmDecodeHex8bit(hex); - } else if (dcs == 72) { - return TinyGsmDecodeHex16bit(hex); - } else { - return hex; - } - } - - bool sendSMS(const String& number, const String& text) - { - sendAT(GF("+CSCS=\"GSM\"")); - waitResponse(); - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - stream.print(text); - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - - bool sendSMS_UTF16(const String& number, const void* text, size_t len) - TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * Location functions - */ - - String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE; - - /* - * Battery functions - */ - - uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; - - int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; - -protected: - - bool modemConnect(const char* host, uint16_t port, uint8_t mux) - { - for (int i=0; i<3; i++) { // TODO: no need for loop? - String ip = dnsIpQuery(host); - - sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port); - int rsp = waitResponse(75000L, - GF(",OK" GSM_NL), - GF(",FAIL" GSM_NL), - GF("+TCPSETUP:Error" GSM_NL)); - if (1 == rsp) { - return true; - } else if (3 == rsp) { - sendAT(GF("+TCPCLOSE="), mux); - waitResponse(); - } - delay(1000); - } - return false; - } - - int modemSend(const void* buff, size_t len, uint8_t mux) - { - sendAT(GF("+TCPSEND="), mux, ',', len); - if (waitResponse(GF(">")) != 1) { - return 0; - } - stream.write((uint8_t*)buff, len); - stream.write((char)0x0D); - stream.flush(); - if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) { - return 0; - } - stream.readStringUntil('\n'); - return len; - } - - bool modemGetConnected(uint8_t mux) - { - sendAT(GF("+CIPSTATUS="), mux); - int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), - GF(",\"INITIAL\"")); - waitResponse(); - return 1 == res; - } - - String dnsIpQuery(const char* host) - { - sendAT(GF("+DNS=\""), host, GF("\"")); - if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(GF("+DNS:OK" GSM_NL)); - res.trim(); - return res; - } - -public: - - /* Utilities */ - - template - void streamWrite(T last) - { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) - { - stream.print(head); - streamWrite(tail...); - } - - bool streamSkipUntil(char c) //TODO: timeout - { - while (true) { - while (!stream.available()) { - TINY_GSM_YIELD(); - } - if (stream.read() == c) { - return true; - } - } - return false; - } - - template - void sendAT(Args... cmd) - { - streamWrite("AT", cmd..., GSM_NL); - stream.flush(); - TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); - } - - // TODO: Optimize this! - uint8_t waitResponse(uint32_t timeout, String& data, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - /*String r1s(r1); r1s.trim(); - String r2s(r2); r2s.trim(); - String r3s(r3); r3s.trim(); - String r4s(r4); r4s.trim(); - String r5s(r5); r5s.trim(); - DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ - data.reserve(64); - int index = 0; - unsigned long startMillis = millis(); - do { - TINY_GSM_YIELD(); - while (stream.available() > 0) { - int a = stream.read(); - if (a <= 0) { - continue; // Skip 0x00 bytes, just in case - } - data += (char)a; - if (r1 && data.endsWith(r1)) { - index = 1; - goto finish; - } else if (r2 && data.endsWith(r2)) { - index = 2; - goto finish; - } else if (r3 && data.endsWith(r3)) { - index = 3; - goto finish; - } else if (r4 && data.endsWith(r4)) { - index = 4; - goto finish; - } else if (r5 && data.endsWith(r5)) { - index = 5; - goto finish; - } else if (data.endsWith(GF("+TCPRECV:"))) { - int mux = stream.readStringUntil(',').toInt(); - int len = stream.readStringUntil(',').toInt(); - int len_orig = len; - if (len > sockets[mux]->rx.free()) { - DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free()); - } else { - DBG("### Got: ", len, "->", sockets[mux]->rx.free()); - } - while (len--) { - while (!stream.available()) { - TINY_GSM_YIELD(); - } - sockets[mux]->rx.put(stream.read()); - } - if (len_orig > sockets[mux]->available()) { // TODO - DBG("### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig); - } - data = ""; - } else if (data.endsWith(GF("+TCPCLOSE:"))) { - int mux = stream.readStringUntil(',').toInt(); - stream.readStringUntil('\n'); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) { - sockets[mux]->sock_connected = false; - } - data = ""; - DBG("### Closed: ", mux); - } - } - } while (millis() - startMillis < timeout); -finish: - if (!index) { - data.trim(); - if (data.length()) { - DBG("### Unhandled:", data); - } - data = ""; - } - return index; - } - - uint8_t waitResponse(uint32_t timeout, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - String data; - return waitResponse(timeout, data, r1, r2, r3, r4, r5); - } - - uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - return waitResponse(1000, r1, r2, r3, r4, r5); - } - -public: - Stream& stream; - -protected: - GsmClient* sockets[TINY_GSM_MUX_COUNT]; -}; - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmClientSIM800.h b/lib/MySensors/drivers/TinyGSM/TinyGsmClientSIM800.h deleted file mode 100644 index 265bdc0c..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmClientSIM800.h +++ /dev/null @@ -1,1057 +0,0 @@ -/** - * file TinyGsmClientSIM800.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmClientSIM800_h -#define TinyGsmClientSIM800_h - -//#define TINY_GSM_DEBUG Serial -//#define TINY_GSM_USE_HEX - -#if !defined(TINY_GSM_RX_BUFFER) -#define TINY_GSM_RX_BUFFER 64 -#endif - -#define TINY_GSM_MUX_COUNT 5 - -#include "TinyGsmCommon.h" - -#define GSM_NL "\r\n" -static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; -static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; - -enum SimStatus { - SIM_ERROR = 0, - SIM_READY = 1, - SIM_LOCKED = 2, -}; - -enum RegStatus { - REG_UNREGISTERED = 0, - REG_SEARCHING = 2, - REG_DENIED = 3, - REG_OK_HOME = 1, - REG_OK_ROAMING = 5, - REG_UNKNOWN = 4, -}; - - -class TinyGsmSim800 -{ - -public: - - class GsmClient : public Client - { - friend class TinyGsmSim800; - typedef TinyGsmFifo RxFifo; - - public: - GsmClient() {} - - GsmClient(TinyGsmSim800& modem, uint8_t mux = 1) - { - init(&modem, mux); - } - - bool init(TinyGsmSim800* modem, uint8_t mux = 1) - { - this->at = modem; - this->mux = mux; - sock_available = 0; - prev_check = 0; - sock_connected = false; - got_data = false; - - at->sockets[mux] = this; - - return true; - } - - public: - virtual int connect(const char *host, uint16_t port) - { - stop(); - TINY_GSM_YIELD(); - rx.clear(); - sock_connected = at->modemConnect(host, port, mux); - return sock_connected; - } - - virtual int connect(IPAddress ip, uint16_t port) - { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return connect(host.c_str(), port); - } - - virtual void stop() - { - TINY_GSM_YIELD(); - at->sendAT(GF("+CIPCLOSE="), mux); - sock_connected = false; - at->waitResponse(); - rx.clear(); - } - - virtual size_t write(const uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - at->maintain(); - return at->modemSend(buf, size, mux); - } - - virtual size_t write(uint8_t c) - { - return write(&c, 1); - } - - virtual int available() - { - TINY_GSM_YIELD(); - if (!rx.size() && sock_connected) { - // Workaround: sometimes SIM800 forgets to notify about data arrival. - // TODO: Currently we ping the module periodically, - // but maybe there's a better indicator that we need to poll - if (millis() - prev_check > 500) { - got_data = true; - prev_check = millis(); - } - at->maintain(); - } - return rx.size() + sock_available; - } - - virtual int read(uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - at->maintain(); - size_t cnt = 0; - while (cnt < size && sock_connected) { - size_t chunk = TinyGsmMin(size-cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } - // TODO: Read directly into user buffer? - at->maintain(); - if (sock_available > 0) { - at->modemRead(rx.free(), mux); - } else { - break; - } - } - return cnt; - } - - virtual int read() - { - uint8_t c; - if (read(&c, 1) == 1) { - return c; - } - return -1; - } - - virtual int peek() - { - return -1; //TODO - } - virtual void flush() - { - at->stream.flush(); - } - - virtual uint8_t connected() - { - if (available()) { - return true; - } - return sock_connected; - } - virtual operator bool() - { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - private: - TinyGsmSim800* at; - uint8_t mux; - uint16_t sock_available; - uint32_t prev_check; - bool sock_connected; - bool got_data; - RxFifo rx; - }; - - class GsmClientSecure : public GsmClient - { - public: - GsmClientSecure() {} - - GsmClientSecure(TinyGsmSim800& modem, uint8_t mux = 1) - : GsmClient(modem, mux) - {} - - public: - virtual int connect(const char *host, uint16_t port) - { - stop(); - TINY_GSM_YIELD(); - rx.clear(); - sock_connected = at->modemConnect(host, port, mux, true); - return sock_connected; - } - }; - -public: - - explicit TinyGsmSim800(Stream& stream) - : stream(stream) - { - memset(sockets, 0, sizeof(sockets)); - } - - /* - * Basic functions - */ - bool begin() - { - return init(); - } - - bool init() - { - if (!testAT()) { - return false; - } - sendAT(GF("&FZ")); // Factory + Reset - waitResponse(); - sendAT(GF("E0")); // Echo Off - if (waitResponse() != 1) { - return false; - } - getSimStatus(); - return true; - } - - void setBaud(unsigned long baud) - { - sendAT(GF("+IPR="), baud); - } - - bool testAT(unsigned long timeout = 10000L) - { - //streamWrite(GF("AAAAA" GSM_NL)); // TODO: extra A's to help detect the baud rate - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("")); - if (waitResponse(200) == 1) { - delay(100); - return true; - } - delay(100); - } - return false; - } - - void maintain() - { - for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) { - GsmClient* sock = sockets[mux]; - if (sock && sock->got_data) { - sock->got_data = false; - sock->sock_available = modemGetAvailable(mux); - } - } - while (stream.available()) { - waitResponse(10, NULL, NULL); - } - } - - bool factoryDefault() - { - sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write - waitResponse(); - sendAT(GF("+IPR=0")); // Auto-baud - waitResponse(); - sendAT(GF("+IFC=0,0")); // No Flow Control - waitResponse(); - sendAT(GF("+ICF=3,3")); // 8 data 0 parity 1 stop - waitResponse(); - sendAT(GF("+CSCLK=0")); // Disable Slow Clock - waitResponse(); - sendAT(GF("&W")); // Write configuration - return waitResponse() == 1; - } - - String getModemInfo() - { - sendAT(GF("I")); - String res; - if (waitResponse(1000L, res) != 1) { - return ""; - } - res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, " "); - res.trim(); - return res; - } - - bool hasSSL() - { -#if defined(TINY_GSM_MODEM_SIM900) - return false; -#else - sendAT(GF("+CIPSSL=?")); - if (waitResponse(GF(GSM_NL "+CIPSSL:")) != 1) { - return false; - } - return waitResponse() == 1; -#endif - } - - /* - * Power functions - */ - - bool restart() - { - if (!testAT()) { - return false; - } - sendAT(GF("+CFUN=0")); - if (waitResponse(10000L) != 1) { - return false; - } - sendAT(GF("+CFUN=1,1")); - if (waitResponse(10000L) != 1) { - return false; - } - delay(3000); - return init(); - } - - bool poweroff() - { - sendAT(GF("+CPOWD=1")); - return waitResponse(GF("NORMAL POWER DOWN")) == 1; - } - - bool radioOff() - { - sendAT(GF("+CFUN=0")); - if (waitResponse(10000L) != 1) { - return false; - } - delay(3000); - return true; - } - - /* - During sleep, the SIM800 module has its serial communication disabled. In order to reestablish communication - pull the DRT-pin of the SIM800 module LOW for at least 50ms. Then use this function to disable sleep mode. - The DTR-pin can then be released again. - */ - bool sleepEnable(bool enable = true) - { - sendAT(GF("+CSCLK="), enable); - return waitResponse() == 1; - } - - /* - * SIM card functions - */ - - bool simUnlock(const char *pin) - { - sendAT(GF("+CPIN=\""), pin, GF("\"")); - return waitResponse() == 1; - } - - String getSimCCID() - { - sendAT(GF("+ICCID")); - if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - String getIMEI() - { - sendAT(GF("+GSN")); - if (waitResponse(GF(GSM_NL)) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - SimStatus getSimStatus(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("+CPIN?")); - if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) { - delay(1000); - continue; - } - int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED")); - waitResponse(); - switch (status) { - case 2: - case 3: - return SIM_LOCKED; - case 1: - return SIM_READY; - default: - return SIM_ERROR; - } - } - return SIM_ERROR; - } - - RegStatus getRegistrationStatus() - { - sendAT(GF("+CREG?")); - if (waitResponse(GF(GSM_NL "+CREG:")) != 1) { - return REG_UNKNOWN; - } - streamSkipUntil(','); // Skip format (0) - int status = stream.readStringUntil('\n').toInt(); - waitResponse(); - return (RegStatus)status; - } - - String getOperator() - { - sendAT(GF("+COPS?")); - if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { - return ""; - } - streamSkipUntil('"'); // Skip mode and format - String res = stream.readStringUntil('"'); - waitResponse(); - return res; - } - - /* - * Generic network functions - */ - - int getSignalQuality() - { - sendAT(GF("+CSQ")); - if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { - return 99; - } - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - bool isNetworkConnected() - { - RegStatus s = getRegistrationStatus(); - return (s == REG_OK_HOME || s == REG_OK_ROAMING); - } - - bool waitForNetwork(unsigned long timeout = 60000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - if (isNetworkConnected()) { - return true; - } - delay(250); - } - return false; - } - - /* - * GPRS functions - */ - bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) - { - gprsDisconnect(); - - // Set the Bearer for the IP - sendAT(GF("+SAPBR=3,1,\"Contype\",\"GPRS\"")); // Set the connection type to GPRS - waitResponse(); - - sendAT(GF("+SAPBR=3,1,\"APN\",\""), apn, '"'); // Set the APN - waitResponse(); - - if (user && strlen(user) > 0) { - sendAT(GF("+SAPBR=3,1,\"USER\",\""), user, '"'); // Set the user name - waitResponse(); - } - if (pwd && strlen(pwd) > 0) { - sendAT(GF("+SAPBR=3,1,\"PWD\",\""), pwd, '"'); // Set the password - waitResponse(); - } - - // Define the PDP context - sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); - waitResponse(); - - // Activate the PDP context - sendAT(GF("+CGACT=1,1")); - waitResponse(60000L); - - // Open the definied GPRS bearer context - sendAT(GF("+SAPBR=1,1")); - waitResponse(85000L); - // Query the GPRS bearer context status - sendAT(GF("+SAPBR=2,1")); - if (waitResponse(30000L) != 1) { - return false; - } - - // Attach to GPRS - sendAT(GF("+CGATT=1")); - if (waitResponse(60000L) != 1) { - return false; - } - - // TODO: wait AT+CGATT? - - // Set to multi-IP - sendAT(GF("+CIPMUX=1")); - if (waitResponse() != 1) { - return false; - } - - // Put in "quick send" mode (thus no extra "Send OK") - sendAT(GF("+CIPQSEND=1")); - if (waitResponse() != 1) { - return false; - } - - // Set to get data manually - sendAT(GF("+CIPRXGET=1")); - if (waitResponse() != 1) { - return false; - } - - // Start Task and Set APN, USER NAME, PASSWORD - sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); - if (waitResponse(60000L) != 1) { - return false; - } - - // Bring Up Wireless Connection with GPRS or CSD - sendAT(GF("+CIICR")); - if (waitResponse(60000L) != 1) { - return false; - } - - // Get Local IP Address, only assigned after connection - sendAT(GF("+CIFSR;E0")); - if (waitResponse(10000L) != 1) { - return false; - } - - // Configure Domain Name Server (DNS) - sendAT(GF("+CDNSCFG=\"8.8.8.8\",\"8.8.4.4\"")); - if (waitResponse() != 1) { - return false; - } - - return true; - } - - bool gprsDisconnect() - { - // Shut the TCP/IP connection - sendAT(GF("+CIPSHUT")); - if (waitResponse(60000L) != 1) { - return false; - } - - sendAT(GF("+CGATT=0")); // Deactivate the bearer context - if (waitResponse(60000L) != 1) { - return false; - } - - return true; - } - - bool isGprsConnected() - { - sendAT(GF("+CGATT?")); - if (waitResponse(GF(GSM_NL "+CGATT:")) != 1) { - return false; - } - int res = stream.readStringUntil('\n').toInt(); - waitResponse(); - if (res != 1) { - return false; - } - - sendAT(GF("+CIFSR;E0")); // Another option is to use AT+CGPADDR=1 - if (waitResponse() != 1) { - return false; - } - - return true; - } - - String getLocalIP() - { - sendAT(GF("+CIFSR;E0")); - String res; - if (waitResponse(10000L, res) != 1) { - return ""; - } - res.replace(GSM_NL "OK" GSM_NL, ""); - res.replace(GSM_NL, ""); - res.trim(); - return res; - } - - IPAddress localIP() - { - return TinyGsmIpFromString(getLocalIP()); - } - - /* - * Phone Call functions - */ - - bool setGsmBusy(bool busy = true) - { - sendAT(GF("+GSMBUSY="), busy ? 1 : 0); - return waitResponse() == 1; - } - - bool callAnswer() - { - sendAT(GF("A")); - return waitResponse() == 1; - } - - // Returns true on pick-up, false on error/busy - bool callNumber(const String& number) - { - if (number == GF("last")) { - sendAT(GF("DL")); - } else { - sendAT(GF("D"), number, ";"); - } - int status = waitResponse(60000L, - GFP(GSM_OK), - GF("BUSY" GSM_NL), - GF("NO ANSWER" GSM_NL), - GF("NO CARRIER" GSM_NL)); - switch (status) { - case 1: - return true; - case 2: - case 3: - return false; - default: - return false; - } - } - - bool callHangup() - { - sendAT(GF("H")); - return waitResponse() == 1; - } - - // 0-9,*,#,A,B,C,D - bool dtmfSend(char cmd, int duration_ms = 100) - { - duration_ms = constrain(duration_ms, 100, 1000); - - sendAT(GF("+VTD="), duration_ms / 100); // VTD accepts in 1/10 of a second - waitResponse(); - - sendAT(GF("+VTS="), cmd); - return waitResponse(10000L) == 1; - } - - /* - * Messaging functions - */ - - String sendUSSD(const String& code) - { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CUSD=1,\""), code, GF("\"")); - if (waitResponse() != 1) { - return ""; - } - if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) { - return ""; - } - stream.readStringUntil('"'); - String hex = stream.readStringUntil('"'); - stream.readStringUntil(','); - int dcs = stream.readStringUntil('\n').toInt(); - - if (dcs == 15) { - return TinyGsmDecodeHex8bit(hex); - } else if (dcs == 72) { - return TinyGsmDecodeHex16bit(hex); - } else { - return hex; - } - } - - bool sendSMS(const String& number, const String& text) - { - sendAT(GF("+CMGF=1")); - waitResponse(); - //Set GSM 7 bit default alphabet (3GPP TS 23.038) - sendAT(GF("+CSCS=\"GSM\"")); - waitResponse(); - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - stream.print(text); - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - - bool sendSMS_UTF16(const String& number, const void* text, size_t len) - { - sendAT(GF("+CMGF=1")); - waitResponse(); - sendAT(GF("+CSCS=\"HEX\"")); - waitResponse(); - sendAT(GF("+CSMP=17,167,0,8")); - waitResponse(); - - sendAT(GF("+CMGS=\""), number, GF("\"")); - if (waitResponse(GF(">")) != 1) { - return false; - } - - uint16_t* t = (uint16_t*)text; - for (size_t i=0; i> 8; - if (c < 0x10) { - stream.print('0'); - } - stream.print(c, HEX); - c = t[i] & 0xFF; - if (c < 0x10) { - stream.print('0'); - } - stream.print(c, HEX); - } - stream.write((char)0x1A); - stream.flush(); - return waitResponse(60000L) == 1; - } - - - /* - * Location functions - */ - - String getGsmLocation() - { - sendAT(GF("+CIPGSMLOC=1,1")); - if (waitResponse(10000L, GF(GSM_NL "+CIPGSMLOC:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - /* - * Battery functions - */ - // Use: float vBatt = modem.getBattVoltage() / 1000.0; - uint16_t getBattVoltage() - { - sendAT(GF("+CBC")); - if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { - return 0; - } - streamSkipUntil(','); // Skip - streamSkipUntil(','); // Skip - - uint16_t res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - int getBattPercent() - { - sendAT(GF("+CBC")); - if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { - return false; - } - stream.readStringUntil(','); - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - -protected: - - bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) - { -#if !defined(TINY_GSM_MODEM_SIM900) - sendAT(GF("+CIPSSL="), ssl); - int rsp = waitResponse(); - if (ssl && rsp != 1) { - return false; - } -#endif - sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); - rsp = waitResponse(75000L, - GF("CONNECT OK" GSM_NL), - GF("CONNECT FAIL" GSM_NL), - GF("ALREADY CONNECT" GSM_NL), - GF("ERROR" GSM_NL), - GF("CLOSE OK" GSM_NL) // Happens when HTTPS handshake fails - ); - return (1 == rsp); - } - - int modemSend(const void* buff, size_t len, uint8_t mux) - { - sendAT(GF("+CIPSEND="), mux, ',', len); - if (waitResponse(GF(">")) != 1) { - return 0; - } - stream.write((uint8_t*)buff, len); - stream.flush(); - if (waitResponse(GF(GSM_NL "DATA ACCEPT:")) != 1) { - return 0; - } - streamSkipUntil(','); // Skip mux - return stream.readStringUntil('\n').toInt(); - } - - size_t modemRead(size_t size, uint8_t mux) - { -#ifdef TINY_GSM_USE_HEX - sendAT(GF("+CIPRXGET=3,"), mux, ',', size); - if (waitResponse(GF("+CIPRXGET:")) != 1) { - return 0; - } -#else - sendAT(GF("+CIPRXGET=2,"), mux, ',', size); - if (waitResponse(GF("+CIPRXGET:")) != 1) { - return 0; - } -#endif - streamSkipUntil(','); // Skip mode 2/3 - streamSkipUntil(','); // Skip mux - size_t len = stream.readStringUntil(',').toInt(); - sockets[mux]->sock_available = stream.readStringUntil('\n').toInt(); - - for (size_t i=0; irx.put(c); - } - waitResponse(); - return len; - } - - size_t modemGetAvailable(uint8_t mux) - { - sendAT(GF("+CIPRXGET=4,"), mux); - size_t result = 0; - if (waitResponse(GF("+CIPRXGET:")) == 1) { - streamSkipUntil(','); // Skip mode 4 - streamSkipUntil(','); // Skip mux - result = stream.readStringUntil('\n').toInt(); - waitResponse(); - } - if (!result) { - sockets[mux]->sock_connected = modemGetConnected(mux); - } - return result; - } - - bool modemGetConnected(uint8_t mux) - { - sendAT(GF("+CIPSTATUS="), mux); - int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), - GF(",\"INITIAL\"")); - waitResponse(); - return 1 == res; - } - -public: - - /* Utilities */ - - template - void streamWrite(T last) - { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) - { - stream.print(head); - streamWrite(tail...); - } - - bool streamSkipUntil(char c) //TODO: timeout - { - while (true) { - while (!stream.available()) { - TINY_GSM_YIELD(); - } - if (stream.read() == c) { - return true; - } - } - return false; - } - - template - void sendAT(Args... cmd) - { - streamWrite("AT", cmd..., GSM_NL); - stream.flush(); - TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); - } - - // TODO: Optimize this! - uint8_t waitResponse(uint32_t timeout, String& data, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - /*String r1s(r1); r1s.trim(); - String r2s(r2); r2s.trim(); - String r3s(r3); r3s.trim(); - String r4s(r4); r4s.trim(); - String r5s(r5); r5s.trim(); - DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ - data.reserve(64); - int index = 0; - unsigned long startMillis = millis(); - do { - TINY_GSM_YIELD(); - while (stream.available() > 0) { - int a = stream.read(); - if (a <= 0) { - continue; // Skip 0x00 bytes, just in case - } - data += (char)a; - if (r1 && data.endsWith(r1)) { - index = 1; - goto finish; - } else if (r2 && data.endsWith(r2)) { - index = 2; - goto finish; - } else if (r3 && data.endsWith(r3)) { - index = 3; - goto finish; - } else if (r4 && data.endsWith(r4)) { - index = 4; - goto finish; - } else if (r5 && data.endsWith(r5)) { - index = 5; - goto finish; - } else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) { - String mode = stream.readStringUntil(','); - if (mode.toInt() == 1) { - int mux = stream.readStringUntil('\n').toInt(); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { - sockets[mux]->got_data = true; - } - data = ""; - } else { - data += mode; - } - } else if (data.endsWith(GF("CLOSED" GSM_NL))) { - int nl = data.lastIndexOf(GSM_NL, data.length()-8); - int coma = data.indexOf(',', nl+2); - int mux = data.substring(nl+2, coma).toInt(); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { - sockets[mux]->sock_connected = false; - } - data = ""; - DBG("### Closed: ", mux); - } - } - } while (millis() - startMillis < timeout); -finish: - if (!index) { - data.trim(); - if (data.length()) { - DBG("### Unhandled:", data); - } - data = ""; - } - return index; - } - - uint8_t waitResponse(uint32_t timeout, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - String data; - return waitResponse(timeout, data, r1, r2, r3, r4, r5); - } - - uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - return waitResponse(1000, r1, r2, r3, r4, r5); - } - -public: - Stream& stream; - -protected: - GsmClient* sockets[TINY_GSM_MUX_COUNT]; -}; - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmClientSIM808.h b/lib/MySensors/drivers/TinyGSM/TinyGsmClientSIM808.h deleted file mode 100644 index d6342a1e..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmClientSIM808.h +++ /dev/null @@ -1,163 +0,0 @@ -/** - * file TinyGsmClientSIM808.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmClientSIM808_h -#define TinyGsmClientSIM808_h - -#include "TinyGsmClientSIM800.h" - -class TinyGsmSim808: public TinyGsmSim800 -{ - -public: - - explicit TinyGsmSim808(Stream& stream) - : TinyGsmSim800(stream) - {} - - /* - * GPS location functions - */ - - // enable GPS - bool enableGPS() - { - uint16_t state; - - sendAT(GF("+CGNSPWR=1")); - if (waitResponse() != 1) { - return false; - } - - return true; - } - - bool disableGPS() - { - uint16_t state; - - sendAT(GF("+CGNSPWR=0")); - if (waitResponse() != 1) { - return false; - } - - return true; - } - - // get the RAW GPS output - // works only with ans SIM808 V2 - String getGPSraw() - { - sendAT(GF("+CGNSINF")); - if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - // get GPS informations - // works only with ans SIM808 V2 - bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) - { - //String buffer = ""; - char chr_buffer[12]; - bool fix = false; - - sendAT(GF("+CGNSINF")); - if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { - return false; - } - - stream.readStringUntil(','); // mode - if ( stream.readStringUntil(',').toInt() == 1 ) { - fix = true; - } - stream.readStringUntil(','); //utctime - *lat = stream.readStringUntil(',').toFloat(); //lat - *lon = stream.readStringUntil(',').toFloat(); //lon - if (alt != NULL) { - *alt = stream.readStringUntil(',').toFloat(); //lon - } - if (speed != NULL) { - *speed = stream.readStringUntil(',').toFloat(); //speed - } - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - stream.readStringUntil(','); - if (vsat != NULL) { - *vsat = stream.readStringUntil(',').toInt(); //viewed satelites - } - if (usat != NULL) { - *usat = stream.readStringUntil(',').toInt(); //used satelites - } - stream.readStringUntil('\n'); - - waitResponse(); - - return fix; - } - - // get GPS time - // works only with SIM808 V2 - bool getGPSTime(int *year, int *month, int *day, int *hour, int *minute, int *second) - { - bool fix = false; - char chr_buffer[12]; - sendAT(GF("+CGNSINF")); - if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { - return false; - } - - for (int i = 0; i < 3; i++) { - String buffer = stream.readStringUntil(','); - buffer.toCharArray(chr_buffer, sizeof(chr_buffer)); - switch (i) { - case 0: - //mode - break; - case 1: - //fixstatus - if ( buffer.toInt() == 1 ) { - fix = buffer.toInt(); - } - break; - case 2: - *year = buffer.substring(0,4).toInt(); - *month = buffer.substring(4,6).toInt(); - *day = buffer.substring(6,8).toInt(); - *hour = buffer.substring(8,10).toInt(); - *minute = buffer.substring(10,12).toInt(); - *second = buffer.substring(12,14).toInt(); - break; - - default: - // if nothing else matches, do the default - // default is optional - break; - } - } - String res = stream.readStringUntil('\n'); - waitResponse(); - - if (fix) { - return true; - } else { - return false; - } - } - -}; - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmClientU201.h b/lib/MySensors/drivers/TinyGSM/TinyGsmClientU201.h deleted file mode 100644 index d5349ace..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmClientU201.h +++ /dev/null @@ -1,789 +0,0 @@ -/** - * file TinyGsmClientU201.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmClientU201_h -#define TinyGsmClientU201_h - -//#define TINY_GSM_DEBUG Serial - -#if !defined(TINY_GSM_RX_BUFFER) -#define TINY_GSM_RX_BUFFER 64 -#endif - -#define TINY_GSM_MUX_COUNT 5 - -#include "TinyGsmCommon.h" - -#define GSM_NL "\r\n" -static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; -static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; - -enum SimStatus { - SIM_ERROR = 0, - SIM_READY = 1, - SIM_LOCKED = 2, -}; - -enum RegStatus { - REG_UNREGISTERED = 0, - REG_SEARCHING = 2, - REG_DENIED = 3, - REG_OK_HOME = 1, - REG_OK_ROAMING = 5, - REG_UNKNOWN = 4, -}; - - -class TinyGsmU201 -{ - -public: - - class GsmClient : public Client - { - friend class TinyGsmU201; - typedef TinyGsmFifo RxFifo; - - public: - GsmClient() {} - - GsmClient(TinyGsmU201& modem, uint8_t mux = 1) - { - init(&modem, mux); - } - - bool init(TinyGsmU201* modem, uint8_t mux = 1) - { - this->at = modem; - this->mux = mux; - sock_available = 0; - sock_connected = false; - got_data = false; - - return true; - } - - public: - virtual int connect(const char *host, uint16_t port) - { - stop(); - TINY_GSM_YIELD(); - rx.clear(); - sock_connected = at->modemConnect(host, port, &mux); - at->sockets[mux] = this; - return sock_connected; - } - - virtual int connect(IPAddress ip, uint16_t port) - { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - return connect(host.c_str(), port); - } - - virtual void stop() - { - TINY_GSM_YIELD(); - at->sendAT(GF("+USOCL="), mux); - sock_connected = false; - at->waitResponse(); - rx.clear(); - } - - virtual size_t write(const uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - at->maintain(); - return at->modemSend(buf, size, mux); - } - - virtual size_t write(uint8_t c) - { - return write(&c, 1); - } - - virtual int available() - { - TINY_GSM_YIELD(); - if (!rx.size() && sock_connected) { - at->maintain(); - } - return rx.size() + sock_available; - } - - virtual int read(uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - at->maintain(); - size_t cnt = 0; - while (cnt < size) { - size_t chunk = TinyGsmMin(size-cnt, rx.size()); - if (chunk > 0) { - rx.get(buf, chunk); - buf += chunk; - cnt += chunk; - continue; - } - // TODO: Read directly into user buffer? - at->maintain(); - if (sock_available > 0) { - at->modemRead(rx.free(), mux); - } else { - break; - } - } - return cnt; - } - - virtual int read() - { - uint8_t c; - if (read(&c, 1) == 1) { - return c; - } - return -1; - } - - virtual int peek() - { - return -1; //TODO - } - virtual void flush() - { - at->stream.flush(); - } - - virtual uint8_t connected() - { - if (available()) { - return true; - } - return sock_connected; - } - virtual operator bool() - { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - private: - TinyGsmU201* at; - uint8_t mux; - uint16_t sock_available; - bool sock_connected; - bool got_data; - RxFifo rx; - }; - - class GsmClientSecure : public GsmClient - { - public: - GsmClientSecure() {} - - GsmClientSecure(TinyGsmU201& modem, uint8_t mux = 1) - : GsmClient(modem, mux) - {} - - public: - virtual int connect(const char *host, uint16_t port) - { - stop(); - TINY_GSM_YIELD(); - rx.clear(); - sock_connected = at->modemConnect(host, port, &mux, true); - at->sockets[mux] = this; - return sock_connected; - } - }; - -public: - -#ifdef GSM_DEFAULT_STREAM - explicit TinyGsmU201(Stream& stream = GSM_DEFAULT_STREAM) -#else - explicit TinyGsmU201(Stream& stream) -#endif - : stream(stream) - { - memset(sockets, 0, sizeof(sockets)); - } - - /* - * Basic functions - */ - bool begin(const char* pin = NULL) - { - return init(pin); - } - - bool init(const char* pin = NULL) - { - if (!testAT()) { - return false; - } - sendAT(GF("E0")); // Echo Off - if (waitResponse() != 1) { - return false; - } - int ret = getSimStatus(); - if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { - simUnlock(pin); - } - return (getSimStatus() == SIM_READY); - } - - void setBaud(unsigned long baud) - { - sendAT(GF("+IPR="), baud); - } - - bool testAT(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("")); - if (waitResponse(200) == 1) { - delay(100); - return true; - } - delay(100); - } - return false; - } - - void maintain() - { - for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) { - GsmClient* sock = sockets[mux]; - if (sock && sock->got_data) { - sock->got_data = false; - sock->sock_available = modemGetAvailable(mux); - } - } - while (stream.available()) { - waitResponse(10, NULL, NULL); - } - } - - bool factoryDefault() - { - sendAT(GF("+UFACTORY=0,1")); // Factory + Reset + Echo Off - waitResponse(); - sendAT(GF("+CFUN=16")); // Auto-baud - return waitResponse() == 1; - } - - String getModemInfo() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool hasSSL() - { - return true; - } - - /* - * Power functions - */ - - bool restart() - { - if (!testAT()) { - return false; - } - sendAT(GF("+CFUN=16")); - if (waitResponse(10000L) != 1) { - return false; - } - delay(3000); - return init(); - } - - bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - /* - * SIM card functions - */ - - bool simUnlock(const char *pin) - { - sendAT(GF("+CPIN=\""), pin, GF("\"")); - return waitResponse() == 1; - } - - String getSimCCID() - { - sendAT(GF("+CCID")); - if (waitResponse(GF(GSM_NL "+CCID:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - String getIMEI() - { - sendAT(GF("+CGSN")); - if (waitResponse(GF(GSM_NL)) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - SimStatus getSimStatus(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - sendAT(GF("+CPIN?")); - if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) { - delay(1000); - continue; - } - int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED")); - waitResponse(); - switch (status) { - case 2: - case 3: - return SIM_LOCKED; - case 1: - return SIM_READY; - default: - return SIM_ERROR; - } - } - return SIM_ERROR; - } - - RegStatus getRegistrationStatus() - { - sendAT(GF("+CGREG?")); - if (waitResponse(GF(GSM_NL "+CGREG:")) != 1) { - return REG_UNKNOWN; - } - streamSkipUntil(','); // Skip format (0) - int status = stream.readStringUntil('\n').toInt(); - waitResponse(); - return (RegStatus)status; - } - - String getOperator() - { - sendAT(GF("+COPS?")); - if (waitResponse(GF(GSM_NL "+COPS:")) != 1) { - return ""; - } - streamSkipUntil('"'); // Skip mode and format - String res = stream.readStringUntil('"'); - waitResponse(); - return res; - } - - /* - * Generic network functions - */ - - int getSignalQuality() - { - sendAT(GF("+CSQ")); - if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { - return 99; - } - int res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - bool isNetworkConnected() - { - RegStatus s = getRegistrationStatus(); - return (s == REG_OK_HOME || s == REG_OK_ROAMING); - } - - bool waitForNetwork(unsigned long timeout = 60000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - if (isNetworkConnected()) { - return true; - } - delay(250); - } - return false; - } - - /* - * GPRS functions - */ - bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) - { - gprsDisconnect(); - - sendAT(GF("+CGATT=1")); - waitResponse(5000L); - - sendAT(GF("+UPSD=0,1,\""), apn, '"'); - waitResponse(); - - if (user && strlen(user) > 0) { - sendAT(GF("+UPSD=0,2,\""), user, '"'); - waitResponse(); - } - if (pwd && strlen(pwd) > 0) { - sendAT(GF("+UPSD=0,3,\""), pwd, '"'); - waitResponse(); - } - - sendAT(GF("+UPSD=0,7,\"0.0.0.0\"")); // Dynamic IP - waitResponse(); - - sendAT(GF("+UPSDA=0,3")); - waitResponse(6000L); - - // Open a GPRS context - sendAT(GF("+UPSND=0,8")); - if (waitResponse(GF(",8,1")) != 1) { - return false; - } - return true; - } - - bool gprsDisconnect() - { - sendAT(GF("+UPSDA=0,4")); - if (waitResponse(60000L) != 1) { - return false; - } - - sendAT(GF("+CGATT=0")); - if (waitResponse(60000L) != 1) { - return false; - } - - return true; - } - - bool isGprsConnected() - { - sendAT(GF("+CGATT?")); - if (waitResponse(GF(GSM_NL "+CGATT:")) != 1) { - return false; - } - int res = stream.readStringUntil('\n').toInt(); - waitResponse(); - if (res != 1) { - return false; - } - - sendAT(GF("+CIFSR")); - if (waitResponse() != 1) { - return false; - } - - return true; - } - - String getLocalIP() - { - sendAT(GF("+CIFSR;E0")); - String res; - if (waitResponse(10000L, res) != 1) { - return ""; - } - res.trim(); - return res; - } - - IPAddress localIP() - { - return TinyGsmIpFromString(getLocalIP()); - } - - /* - * Phone Call functions - */ - - bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool callAnswer() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool callNumber(const String& number) TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool callHangup() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - /* - * Messaging functions - */ - - String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool sendSMS(const String& number, const String& text) TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool sendSMS_UTF16(const String& number, const void* text, - size_t len) TINY_GSM_ATTR_NOT_IMPLEMENTED; - - - /* - * Location functions - */ - - String getGsmLocation() - { - sendAT(GF("+ULOC=2,3,0,120,1")); - if (waitResponse(GF(GSM_NL "+UULOC:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - /* - * Battery functions - */ - // Use: float vBatt = modem.getBattVoltage() / 1000.0; - uint16_t getBattVoltage() - { - sendAT(GF("+CIND")); - if (waitResponse(GF(GSM_NL "+CIND:")) != 1) { - return 0; - } - - uint16_t res = stream.readStringUntil(',').toInt(); - waitResponse(); - return res; - } - - int getBattPercent() TINY_GSM_ATTR_NOT_IMPLEMENTED; - -protected: - - bool modemConnect(const char* host, uint16_t port, uint8_t* mux, bool ssl = false) - { - sendAT(GF("+USOCR=6")); - if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) { - return false; - } - *mux = stream.readStringUntil('\n').toInt(); - waitResponse(); - - if (ssl) { - sendAT(GF("+USOSEC="), *mux, ",1"); - waitResponse(); - } - - sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port); - int rsp = waitResponse(75000L); - return (1 == rsp); - } - - int modemSend(const void* buff, size_t len, uint8_t mux) - { - sendAT(GF("+USOWR="), mux, ',', len); - if (waitResponse(GF("@")) != 1) { - return -1; - } - // 50ms delay, see AT manual section 25.10.4 - delay(50); - stream.write((uint8_t*)buff, len); - stream.flush(); - if (waitResponse(GF(GSM_NL "+USOWR:")) != 1) { - return -1; - } - streamSkipUntil(','); // Skip mux - return stream.readStringUntil('\n').toInt(); - } - - size_t modemRead(size_t size, uint8_t mux) - { - sendAT(GF("+USORD="), mux, ',', size); - if (waitResponse(GF(GSM_NL "+USORD:")) != 1) { - return 0; - } - streamSkipUntil(','); // Skip mux - size_t len = stream.readStringUntil(',').toInt(); - streamSkipUntil('\"'); - - for (size_t i=0; irx.put(c); - } - streamSkipUntil('\"'); - waitResponse(); - return len; - } - - size_t modemGetAvailable(uint8_t mux) - { - sendAT(GF("+USORD="), mux, ',', 0); - size_t result = 0; - if (waitResponse(GF(GSM_NL "+USORD:")) == 1) { - streamSkipUntil(','); // Skip mux - result = stream.readStringUntil('\n').toInt(); - waitResponse(); - } - if (!result) { - sockets[mux]->sock_connected = modemGetConnected(mux); - } - return result; - } - - bool modemGetConnected(uint8_t mux) - { - sendAT(GF("+USOCTL="), mux, ",10"); - if (waitResponse(GF(GSM_NL "+USOCTL:")) != 1) { - return false; - } - - streamSkipUntil(','); // Skip mux - streamSkipUntil(','); // Skip type - int result = stream.readStringUntil('\n').toInt(); - - return result != 0; - } - -public: - - /* Utilities */ - - template - void streamWrite(T last) - { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) - { - stream.print(head); - streamWrite(tail...); - } - - bool streamSkipUntil(char c) //TODO: timeout - { - while (true) { - while (!stream.available()) { - TINY_GSM_YIELD(); - } - if (stream.read() == c) { - return true; - } - } - return false; - } - - template - void sendAT(Args... cmd) - { - streamWrite("AT", cmd..., GSM_NL); - stream.flush(); - TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); - } - - // TODO: Optimize this! - uint8_t waitResponse(uint32_t timeout, String& data, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - /*String r1s(r1); r1s.trim(); - String r2s(r2); r2s.trim(); - String r3s(r3); r3s.trim(); - String r4s(r4); r4s.trim(); - String r5s(r5); r5s.trim(); - DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ - data.reserve(64); - int index = 0; - unsigned long startMillis = millis(); - do { - TINY_GSM_YIELD(); - while (stream.available() > 0) { - int a = stream.read(); - if (a < 0) { - continue; - } - data += (char)a; - if (r1 && data.endsWith(r1)) { - index = 1; - goto finish; - } else if (r2 && data.endsWith(r2)) { - index = 2; - goto finish; - } else if (r3 && data.endsWith(r3)) { - index = 3; - goto finish; - } else if (r4 && data.endsWith(r4)) { - index = 4; - goto finish; - } else if (r5 && data.endsWith(r5)) { - index = 5; - goto finish; - } else if (data.endsWith(GF(GSM_NL "+UUSORD:"))) { - int mux = stream.readStringUntil(',').toInt(); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { - sockets[mux]->got_data = true; - } - data = ""; - } else if (data.endsWith(GF(GSM_NL "+UUSOCL:"))) { - int mux = stream.readStringUntil('\n').toInt(); - if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) { - sockets[mux]->sock_connected = false; - } - data = ""; - DBG("### Closed: ", mux); - } - } - } while (millis() - startMillis < timeout); -finish: - if (!index) { - data.trim(); - if (data.length()) { - DBG("### Unhandled:", data); - } - data = ""; - } - return index; - } - - uint8_t waitResponse(uint32_t timeout, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - String data; - return waitResponse(timeout, data, r1, r2, r3, r4, r5); - } - - uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - return waitResponse(1000, r1, r2, r3, r4, r5); - } - -public: - Stream& stream; - -protected: - GsmClient* sockets[TINY_GSM_MUX_COUNT]; -}; - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmClientXBee.h b/lib/MySensors/drivers/TinyGSM/TinyGsmClientXBee.h deleted file mode 100644 index 8efef857..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmClientXBee.h +++ /dev/null @@ -1,752 +0,0 @@ -/** - * file TinyGsmClientXBee.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmClientXBee_h -#define TinyGsmClientXBee_h - -//#define TINY_GSM_DEBUG Serial - -#if !defined(TINY_GSM_RX_BUFFER) -#define TINY_GSM_RX_BUFFER 256 -#endif - -#define TINY_GSM_MUX_COUNT 1 // Multi-plexing isn't supported using command mode - -#include "TinyGsmCommon.h" - -#define GSM_NL "\r" -static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; -static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL; - -enum SimStatus { - SIM_ERROR = 0, - SIM_READY = 1, - SIM_LOCKED = 2, -}; - -enum XBeeType { - S6B = 0, - LTEC1 = 1, -}; - -enum RegStatus { - REG_UNREGISTERED = 0, - REG_SEARCHING = 2, - REG_DENIED = 3, - REG_OK_HOME = 1, - REG_OK_ROAMING = 5, - REG_UNKNOWN = 4, -}; - - -class TinyGsm -{ - -public: - - class GsmClient : public Client - { - friend class TinyGsm; - - public: - GsmClient() {} - - GsmClient(TinyGsm& modem, uint8_t mux = 0) - { - init(&modem, mux); - } - - bool init(TinyGsm* modem, uint8_t mux = 0) - { - this->at = modem; - this->mux = mux; - sock_connected = false; - - at->sockets[mux] = this; - - return true; - } - - public: - virtual int connect(const char *host, uint16_t port) - { - at->streamClear(); // Empty anything remaining in the buffer; - at->commandMode(); - sock_connected = at->modemConnect(host, port, mux, false); - at->writeChanges(); - at->exitCommand(); - return sock_connected; - } - - virtual int connect(IPAddress ip, uint16_t port) - { - at->streamClear(); // Empty anything remaining in the buffer; - at->commandMode(); - sock_connected = at->modemConnect(ip, port, mux, false); - at->writeChanges(); - at->exitCommand(); - return sock_connected; - } - - // This is a hack to shut the socket by setting the timeout to zero and - // then sending an empty line to the server. - virtual void stop() - { - at->streamClear(); // Empty anything remaining in the buffer; - at->commandMode(); - at->sendAT(GF("TM0")); // Set socket timeout to 0; - at->waitResponse(); - at->writeChanges(); - at->exitCommand(); - at->modemSend("", 1, mux); - at->commandMode(); - at->sendAT(GF("TM64")); // Set socket timeout back to 10seconds; - at->waitResponse(); - at->writeChanges(); - at->exitCommand(); - at->streamClear(); // Empty anything remaining in the buffer; - sock_connected = false; - } - - virtual size_t write(const uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - //at->maintain(); - return at->modemSend(buf, size, mux); - } - - virtual size_t write(uint8_t c) - { - return write(&c, 1); - } - - virtual int available() - { - TINY_GSM_YIELD(); - return at->stream.available(); - } - - virtual int read(uint8_t *buf, size_t size) - { - TINY_GSM_YIELD(); - return at->stream.readBytes(buf, size); - } - - virtual int read() - { - TINY_GSM_YIELD(); - return at->stream.read(); - } - - virtual int peek() - { - return at->stream.peek(); - } - virtual void flush() - { - at->stream.flush(); - } - - virtual uint8_t connected() - { - if (available()) { - return true; - } - return sock_connected; - } - virtual operator bool() - { - return connected(); - } - - /* - * Extended API - */ - - String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED; - - private: - TinyGsm* at; - uint8_t mux; - bool sock_connected; - }; - - class GsmClientSecure : public GsmClient - { - public: - GsmClientSecure() {} - - GsmClientSecure(TinyGsm& modem, uint8_t mux = 1) - : GsmClient(modem, mux) - {} - - public: - virtual int connect(const char *host, uint16_t port) - { - at->streamClear(); // Empty anything remaining in the buffer; - at->commandMode(); - sock_connected = at->modemConnect(host, port, mux, true); - at->writeChanges(); - at->exitCommand(); - return sock_connected; - } - - virtual int connect(IPAddress ip, uint16_t port) - { - at->streamClear(); // Empty anything remaining in the buffer; - at->commandMode(); - sock_connected = at->modemConnect(ip, port, mux, true); - at->writeChanges(); - at->exitCommand(); - return sock_connected; - } - }; - -public: - - explicit TinyGsm(Stream& stream) - : stream(stream) - { - memset(sockets, 0, sizeof(sockets)); - } - - /* - * Basic functions - */ - bool begin() - { - return init(); - } - - bool init() - { - guardTime = 1100; - commandMode(); - sendAT(GF("AP0")); // Put in transparent mode - waitResponse(); - sendAT(GF("GT64")); // shorten the guard time to 100ms - waitResponse(); - writeChanges(); - sendAT(GF("HS")); // Get the "Hardware Series"; 0x601 for S6B (Wifi) - // wait for the response - unsigned long startMillis = millis(); - while (!stream.available() && millis() - startMillis < 1000) {}; - String res = streamReadUntil('\r'); // Does not send an OK, just the result - exitCommand(); - if (res == "601") { - beeType = S6B; - } else { - beeType = LTEC1; - } - guardTime = 125; - return true; - } - - bool testAT(unsigned long timeout = 10000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - if (commandMode()) { - sendAT(); - if (waitResponse(200) == 1) { - return true; - } - exitCommand(); - } - delay(100); - } - return false; - } - - void maintain() {} - - bool factoryDefault() - { - commandMode(); - sendAT(GF("RE")); - bool ret_val = waitResponse() == 1; - writeChanges(); - exitCommand(); - return ret_val; - } - - bool hasSSL() - { - if (beeType == S6B) { - return false; - } else { - return true; - } - } - - /* - * Power functions - */ - - bool restart() - { - commandMode(); - sendAT(GF("FR")); - if (waitResponse() != 1) { - return false; - } - delay (2000); // Actually resets about 2 seconds later - for (unsigned long start = millis(); millis() - start < 60000L; ) { - if (commandMode()) { - exitCommand(); - return true; - } - } - exitCommand(); - return false;; - } - - void setupPinSleep() - { - commandMode(); - sendAT(GF("SM"),1); - waitResponse(); - if (beeType == S6B) { - sendAT(GF("SO"),200); - waitResponse(); - } - writeChanges(); - exitCommand(); - } - - /* - * SIM card functions - */ - - bool simUnlock(const char *pin) // Not supported - { - return false; - } - - String getSimCCID() - { - commandMode(); - sendAT(GF("S#")); - // wait for the response - unsigned long startMillis = millis(); - while (!stream.available() && millis() - startMillis < 1000) {}; - String res = streamReadUntil('\r'); // Does not send an OK, just the result - exitCommand(); - return res; - } - - String getIMEI() - { - commandMode(); - sendAT(GF("IM")); - // wait for the response - unsigned long startMillis = millis(); - while (!stream.available() && millis() - startMillis < 1000) {}; - String res = streamReadUntil('\r'); // Does not send an OK, just the result - exitCommand(); - return res; - } - - SimStatus getSimStatus(unsigned long timeout = 10000L) - { - return SIM_READY; // unsupported - } - - RegStatus getRegistrationStatus() - { - commandMode(); - sendAT(GF("AI")); - // wait for the response - unsigned long startMillis = millis(); - while (!stream.available() && millis() - startMillis < 1000) {}; - String res = streamReadUntil('\r'); // Does not send an OK, just the result - exitCommand(); - - if(res == GF("0")) { - return REG_OK_HOME; - } - - else if(res == GF("13") || res == GF("2A")) { - return REG_UNREGISTERED; - } - - else if(res == GF("FF") || res == GF("22") || res == GF("23") || - res == GF("40") || res == GF("41") || res == GF("42")) { - return REG_SEARCHING; - } - - else if(res == GF("24") || res == GF("25") || res == GF("27")) { - return REG_DENIED; - } - - else { - return REG_UNKNOWN; - } - } - - String getOperator() - { - commandMode(); - sendAT(GF("MN")); - // wait for the response - unsigned long startMillis = millis(); - while (!stream.available() && millis() - startMillis < 1000) {}; - String res = streamReadUntil('\r'); // Does not send an OK, just the result - exitCommand(); - return res; - } - - /* - * Generic network functions - */ - - int getSignalQuality() - { - commandMode(); - if (beeType == S6B) { - sendAT(GF("LM")); // ask for the "link margin" - the dB above sensitivity - } else { - sendAT(GF("DB")); // ask for the cell strength in dBm - } - // wait for the response - unsigned long startMillis = millis(); - while (!stream.available() && millis() - startMillis < 1000) {}; - char buf[2] = {0}; // Set up buffer for response - buf[0] = streamRead(); - buf[1] = streamRead(); - // DBG(buf[0], buf[1], "\n"); - exitCommand(); - int intr = strtol(buf, 0, 16); - if (beeType == S6B) { - return -93 + intr; // the maximum sensitivity is -93dBm - } else { - return -1*intr; // need to convert to negative number - } - } - - bool isNetworkConnected() - { - RegStatus s = getRegistrationStatus(); - return (s == REG_OK_HOME || s == REG_OK_ROAMING); - } - - bool waitForNetwork(unsigned long timeout = 60000L) - { - for (unsigned long start = millis(); millis() - start < timeout; ) { - if (isNetworkConnected()) { - return true; - } - delay(250); - } - return false; - } - - /* - * WiFi functions - */ - bool networkConnect(const char* ssid, const char* pwd) - { - - commandMode(); - - sendAT(GF("EE"), 2); // Set security to WPA2 - waitResponse(); - - sendAT(GF("ID"), ssid); - if (waitResponse() != 1) { - goto fail; - } - - sendAT(GF("PK"), pwd); - if (waitResponse() != 1) { - goto fail; - } - - writeChanges(); - exitCommand(); - - return true; - -fail: - exitCommand(); - return false; - } - - bool networkDisconnect() - { - return false; // Doesn't support disconnecting - } - - String getLocalIP() - { - commandMode(); - sendAT(GF("MY")); - String IPaddr; - IPaddr.reserve(16); - // wait for the response - unsigned long startMillis = millis(); - while (stream.available() < 8 && millis() - startMillis < 30000) {}; - IPaddr = streamReadUntil('\r'); // read result - return IPaddr; - } - - IPAddress localIP() - { - return TinyGsmIpFromString(getLocalIP()); - } - - /* - * GPRS functions - */ - bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) - { - commandMode(); - sendAT(GF("AN"), apn); // Set the APN - waitResponse(); - writeChanges(); - exitCommand(); - return true; - } - - bool gprsDisconnect() // TODO - { - return false; - } - - /* - * Messaging functions - */ - - String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED; - - bool sendSMS(const String& number, const String& text) - { - commandMode(); - sendAT(GF("IP"), 2); // Put in text messaging mode - waitResponse(); - sendAT(GF("PH"), number); // Set the phone number - waitResponse(); - sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriabe return) - waitResponse(); - writeChanges(); - exitCommand(); - stream.print(text); - stream.write((char)0x0D); // close off with the carriage return - return true; - } - - -private: - - int modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) - { - sendAT(GF("LA"), host); - String strIP; - strIP.reserve(16); - // wait for the response - unsigned long startMillis = millis(); - while (stream.available() < 8 && millis() - startMillis < 30000) {}; - strIP = streamReadUntil('\r'); // read result - IPAddress ip = TinyGsmIpFromString(strIP); - return modemConnect(ip, port, mux, ssl); - } - - int modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false) - { - String host; - host.reserve(16); - host += ip[0]; - host += "."; - host += ip[1]; - host += "."; - host += ip[2]; - host += "."; - host += ip[3]; - if (ssl) { - sendAT(GF("IP"), 4); // Put in TCP mode - waitResponse(); - } else { - sendAT(GF("IP"), 1); // Put in TCP mode - waitResponse(); - } - sendAT(GF("DL"), host); // Set the "Destination Address Low" - waitResponse(); - sendAT(GF("DE"), String(port, HEX)); // Set the destination port - int rsp = waitResponse(); - return rsp; - } - - int modemSend(const void* buff, size_t len, uint8_t mux = 0) - { - stream.write((uint8_t*)buff, len); - stream.flush(); - return len; - } - - bool modemGetConnected(uint8_t mux = 0) - { - commandMode(); - sendAT(GF("AI")); - int res = waitResponse(GF("0")); - exitCommand(); - return 1 == res; - } - -public: - - /* Utilities */ - - template - void streamWrite(T last) - { - stream.print(last); - } - - template - void streamWrite(T head, Args... tail) - { - stream.print(head); - streamWrite(tail...); - } - - int streamRead() - { - return stream.read(); - } - - String streamReadUntil(char c) - { - TINY_GSM_YIELD(); - String return_string = stream.readStringUntil(c); - return_string.trim(); - // DBG(return_string, c); - return return_string; - } - - void streamClear(void) - { - while (stream.available()) { - streamRead(); - } - } - - bool commandMode(void) - { - delay(guardTime); // cannot send anything for 1 second before entering command mode - streamWrite(GF("+++")); // enter command mode - // DBG("\r\n+++\r\n"); - return 1 == waitResponse(guardTime*2); - } - - void writeChanges(void) - { - sendAT(GF("WR")); // Write changes to flash - waitResponse(); - sendAT(GF("AC")); // Apply changes - waitResponse(); - } - - void exitCommand(void) - { - sendAT(GF("CN")); // Exit command mode - waitResponse(); - } - - template - void sendAT(Args... cmd) - { - streamWrite("AT", cmd..., GSM_NL); - stream.flush(); - TINY_GSM_YIELD(); - //DBG("### AT:", cmd...); - } - - // TODO: Optimize this! - uint8_t waitResponse(uint32_t timeout, String& data, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - /*String r1s(r1); r1s.trim(); - String r2s(r2); r2s.trim(); - String r3s(r3); r3s.trim(); - String r4s(r4); r4s.trim(); - String r5s(r5); r5s.trim(); - DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/ - data.reserve(64); - int index = 0; - unsigned long startMillis = millis(); - do { - TINY_GSM_YIELD(); - while (stream.available() > 0) { - int a = streamRead(); - if (a <= 0) { - continue; // Skip 0x00 bytes, just in case - } - data += (char)a; - if (r1 && data.endsWith(r1)) { - index = 1; - goto finish; - } else if (r2 && data.endsWith(r2)) { - index = 2; - goto finish; - } else if (r3 && data.endsWith(r3)) { - index = 3; - goto finish; - } else if (r4 && data.endsWith(r4)) { - index = 4; - goto finish; - } else if (r5 && data.endsWith(r5)) { - index = 5; - goto finish; - } - } - } while (millis() - startMillis < timeout); -finish: - if (!index) { - data.trim(); - data.replace(GSM_NL GSM_NL, GSM_NL); - data.replace(GSM_NL, "\r\n" " "); - if (data.length()) { - DBG("### Unhandled:", data, "\r\n"); - } else { - DBG("### NO RESPONSE!\r\n"); - } - } else { - data.trim(); - data.replace(GSM_NL GSM_NL, GSM_NL); - data.replace(GSM_NL, "\r\n "); - if (data.length()) { - // DBG("<<< ", data); - } - } - return index; - } - - uint8_t waitResponse(uint32_t timeout, - GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - String data; - return waitResponse(timeout, data, r1, r2, r3, r4, r5); - } - - uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR), - GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) - { - return waitResponse(1000, r1, r2, r3, r4, r5); - } - -public: - Stream& stream; - -protected: - int guardTime; - XBeeType beeType; - GsmClient* sockets[TINY_GSM_MUX_COUNT]; -}; - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/TinyGsmCommon.h b/lib/MySensors/drivers/TinyGSM/TinyGsmCommon.h deleted file mode 100644 index 458cc90f..00000000 --- a/lib/MySensors/drivers/TinyGSM/TinyGsmCommon.h +++ /dev/null @@ -1,195 +0,0 @@ -/** - * file TinyGsmCommon.h - * author Volodymyr Shymanskyy - * license LGPL-3.0 - * copyright Copyright (c) 2016 Volodymyr Shymanskyy - * date Nov 2016 - */ - -#ifndef TinyGsmCommon_h -#define TinyGsmCommon_h - -#if defined(SPARK) || defined(PARTICLE) -#include "Particle.h" -#elif defined(ARDUINO) -#if ARDUINO >= 100 -#include "Arduino.h" -#else -#include "WProgram.h" -#endif -#endif - -#include -#include "TinyGsmFifo.h" - -#ifndef TINY_GSM_YIELD -#define TINY_GSM_YIELD() { delay(0); } -#endif - -#define TINY_GSM_ATTR_NOT_AVAILABLE __attribute__((error("Not available on this modem type"))) -#define TINY_GSM_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented"))) - -#if defined(__AVR__) -#define TINY_GSM_PROGMEM PROGMEM -typedef const __FlashStringHelper* GsmConstStr; -#define GFP(x) (reinterpret_cast(x)) -#define GF(x) F(x) -#else -#define TINY_GSM_PROGMEM -typedef const char* GsmConstStr; -#define GFP(x) x -#define GF(x) x -#endif - -#ifdef TINY_GSM_DEBUG -namespace -{ -template -static void DBG(T last) -{ - TINY_GSM_DEBUG.println(last); -} - -template -static void DBG(T head, Args... tail) -{ - TINY_GSM_DEBUG.print(head); - TINY_GSM_DEBUG.print(' '); - DBG(tail...); -} -} -#else -#define DBG(...) -#endif - -template -const T& TinyGsmMin(const T& a, const T& b) -{ - return (b < a) ? b : a; -} - -template -const T& TinyGsmMax(const T& a, const T& b) -{ - return (b < a) ? a : b; -} - -template -uint32_t TinyGsmAutoBaud(T& SerialAT, uint32_t minimum = 9600, uint32_t maximum = 115200) -{ - static uint32_t rates[] = { 115200, 57600, 38400, 19200, 9600, 74400, 74880, 230400, 460800, 2400, 4800, 14400, 28800 }; - - for (unsigned i = 0; i < sizeof(rates)/sizeof(rates[0]); i++) { - uint32_t rate = rates[i]; - if (rate < minimum || rate > maximum) { - continue; - } - - DBG("Trying baud rate", rate, "..."); - SerialAT.begin(rate); - delay(10); - for (int i=0; i<3; i++) { - SerialAT.print("AT\r\n"); - String input = SerialAT.readString(); - if (input.indexOf("OK") >= 0) { - DBG("Modem responded at rate", rate); - return rate; - } - } - } - return 0; -} - -static inline -IPAddress TinyGsmIpFromString(const String& strIP) -{ - int Parts[4] = {0, }; - int Part = 0; - for (uint8_t i=0; i 3) { - return IPAddress(0,0,0,0); - } - continue; - } else if (c >= '0' && c <= '9') { - Parts[Part] *= 10; - Parts[Part] += c - '0'; - } else { - if (Part == 3) { - break; - } - } - } - return IPAddress(Parts[0], Parts[1], Parts[2], Parts[3]); -} - -static inline -String TinyGsmDecodeHex7bit(String &instr) -{ - String result; - byte reminder = 0; - int bitstate = 7; - for (unsigned i=0; i> bitstate; - bitstate--; - if (bitstate == 0) { - char c = reminder; - result += c; - reminder = 0; - bitstate = 7; - } - } - return result; -} - -static inline -String TinyGsmDecodeHex8bit(String &instr) -{ - String result; - for (unsigned i=0; i - -class TinyGsmFifo -{ -public: - - TinyGsmFifo() - { - clear(); - } - - void clear() - { - _r = 0; - _w = 0; - } - - // writing thread/context API - //------------------------------------------------------------- - - bool writeable(void) - { - return free() > 0; - } - - int free(void) - { - int s = _r - _w; - if (s <= 0) { - s += N; - } - return s - 1; - } - - bool put(const T& c) - { - int i = _w; - int j = i; - i = _inc(i); - if (i == _r) { // !writeable() - return false; - } - _b[j] = c; - _w = i; - return true; - } - - int put(const T* p, int n, bool t = false) - { - int c = n; - while (c) { - int f; - while ((f = free()) == 0) { // wait for space - if (!t) { - return n - c; // no more space and not blocking - } - /* nothing / just wait */; - } - // check free space - if (c < f) { - f = c; - } - int w = _w; - int m = N - w; - // check wrap - if (f > m) { - f = m; - } - memcpy(&_b[w], p, f); - _w = _inc(w, f); - c -= f; - p += f; - } - return n - c; - } - - // reading thread/context API - // -------------------------------------------------------- - - bool readable(void) - { - return (_r != _w); - } - - size_t size(void) - { - int s = _w - _r; - if (s < 0) { - s += N; - } - return s; - } - - bool get(T* p) - { - int r = _r; - if (r == _w) { // !readable() - return false; - } - *p = _b[r]; - _r = _inc(r); - return true; - } - - int get(T* p, int n, bool t = false) - { - int c = n; - while (c) { - int f; - for (;;) { // wait for data - f = size(); - if (f) { - break; // free space - } - if (!t) { - return n - c; // no space and not blocking - } - /* nothing / just wait */; - } - // check available data - if (c < f) { - f = c; - } - int r = _r; - int m = N - r; - // check wrap - if (f > m) { - f = m; - } - memcpy(p, &_b[r], f); - _r = _inc(r, f); - c -= f; - p += f; - } - return n - c; - } - -private: - int _inc(int i, int n = 1) - { - return (i + n) % N; - } - - T _b[N]; - int _w; - int _r; -}; - -#endif diff --git a/lib/MySensors/drivers/TinyGSM/keywords.txt b/lib/MySensors/drivers/TinyGSM/keywords.txt deleted file mode 100644 index 33f98c42..00000000 --- a/lib/MySensors/drivers/TinyGSM/keywords.txt +++ /dev/null @@ -1,26 +0,0 @@ -####################################### -# Data types (KEYWORD1) -####################################### -TinyGsm KEYWORD1 -TinyGsmClient KEYWORD1 -TinyGsmClientSecure KEYWORD1 - -SerialAT KEYWORD1 -SerialMon KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### -begin KEYWORD2 -restart KEYWORD2 -waitForNetwork KEYWORD2 -getSimStatus KEYWORD2 -gprsConnect KEYWORD2 -gprsDisconnect KEYWORD2 -isGprsConnected KEYWORD2 -isNetworkConnected KEYWORD2 -factoryReset KEYWORD2 - -####################################### -# Literals (LITERAL1) -####################################### diff --git a/lib/MySensors/drivers/extEEPROM/LICENSE.md b/lib/MySensors/drivers/extEEPROM/LICENSE.md deleted file mode 100644 index ce9bb713..00000000 --- a/lib/MySensors/drivers/extEEPROM/LICENSE.md +++ /dev/null @@ -1,8 +0,0 @@ -# Arduino External EEPROM Library v3 # -http://github.com/JChristensen/extEEPROM -LICENSE file -Jack Christensen Jul 2014 - -![CC BY-SA](http://mirrors.creativecommons.org/presskit/buttons/88x31/png/by-sa.png) -## CC BY-SA ## -"Arduino External EEPROM Library" by Jack Christensen is licensed under [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/). \ No newline at end of file diff --git a/lib/MySensors/drivers/extEEPROM/ReadMe.md b/lib/MySensors/drivers/extEEPROM/ReadMe.md deleted file mode 100644 index 594336a9..00000000 --- a/lib/MySensors/drivers/extEEPROM/ReadMe.md +++ /dev/null @@ -1,226 +0,0 @@ -# Arduino External EEPROM Library v3.4 # - -Original library by http://github.com/JChristensen/extEEPROM - -## Introduction ## -**Arduino External EEPROM Library** - -This library will work with most I2C serial EEPROM chips between 2k bits and 2048k bits (2M bits) in size. Multiple EEPROMs on the bus are supported as a single address space. I/O across block, page and device boundaries is supported. Certain assumptions are made regarding the EEPROM device addressing. These assumptions should be true for most EEPROMs but there are exceptions, so read the datasheet and know your hardware. - -The library should also work for EEPROMs smaller than 2k bits, assuming that there is only one EEPROM on the bus and also that the user is careful to not exceed the maximum address for the EEPROM. - -The **extEEPROM Library** has been tested with: -- Microchip 24AA02E48 (2k bit) -- 24xx32 (32k bit, thanks to Richard M) -- Microchip 24LC256 (256k bit) -- Microchip 24FC1026 (1M bit, thanks to Gabriele B on the Arduino forum) -- ST Micro M24M02 (2M bit) -- Atmel AT24C256C (32k x 8, thanks to Searobin) - -The **extEEPROM Library** will **NOT** work with Microchip 24xx1025 as its control byte does not conform to the following assumptions. - -**Device addressing assumptions:** -- The I2C address sequence consists of a control byte followed by one address byte (for EEPROMs <= 16k bits) or two address bytes (for EEPROMs > 16k bits). -- The three least-significant bits in the control byte (excluding the R/W bit) comprise the three most-significant bits for the entire address space, i.e. all chips on the bus. As such, these may be chip-select bits or block-select bits (for individual chips that have an internal block organization), or a combination of both (in which case the block-select bits must be of lesser significance than the chip-select bits). -- Regardless of the number of bits needed to address the entire address space, the three most-significant bits always go in the control byte. Depending on EEPROM device size, this may result in one or more of the most significant bits in the I2C address bytes being unused (or "don't care" bits). -- An EEPROM contains an integral number of pages. - -Note that the Arduino Wire library has a buffer size of 32 bytes. This limits the size of physical I/Os that can be done to EEPROM. For writes, one or two bytes are used for the address, so writing is therefore limited to 31 or 30 bytes. Because the **extEEPROM Library** will handle I/O across block, page and device boundaries, the only consequence this has for the user is one of efficiency; arbitrarily large blocks of data can be written and read; however, carefully chosen block sizes may reduce the number of physical I/Os needed. - -## Installation ## - -### Install with the Library Manager -- For Arduino IDE versions 1.6.2 and up, add library by selecting "Manage Libraries..." from the "Include Library" submenu within the Sketch menu. -- The library manager will open and you will find a list of libraries that are already installed or ready for installation. Scroll the list to find **extEEPROM** library and click on it. - - Select the version of the library you want to install. - - Click on install and wait for the IDE to install the new library. Downloading may take time depending on your connection speed. - - Once it has finished, an Installed tag should appear, You can close the library manager. - -### Manual Install -- Go to http://github.com/PaoloP74/extEEPROM, click the **Download ZIP** button and save the ZIP file to a convenient location on your PC. -- Uncompress the downloaded file. This will result in a folder containing all the files for the library, that has a name that includes the branch name, usually **extEEPROM-master**. -- Rename the folder to just **extEEPROM**. -- Copy the renamed folder to the Arduino sketchbook\libraries folder. - -## Examples ## -The following example sketch is included with the **extEEPROM Library**: -- **eepromReadWrite** -- **eepromTest:** Writes 32-bit integers to the entire EEPROM address space, starting at address 0 and continuing to the topmost address. These are then read back in and verified; any discrepancies are reported to the serial monitor. -- **eepromTest_Wire1** -## Usage notes ## -The **extEEPROM Library** is designed for use with Arduino version 1.0 or later. - -To use the **extEEPROM Library**, the standard [Arduino Wire library](http://arduino.cc/en/Reference/Wire) must also be included. For brevity, this include is not repeated in the examples below: -```c++ -#include //http://arduino.cc/en/Reference/Wire (included with Arduino IDE) -``` -## Enumerations ## -### eeprom_size_t -##### Description -EEPROM device size in k-bits. Many manufacturers' EEPROM part numbers are designated in k-bits. -##### Values -- kbits_2 -- kbits_4 -- kbits_8 -- kbits_16 -- kbits_32 -- kbits_64 -- kbits_128 -- kbits_256 -- kbits_512 -- kbits_1024 -- kbits_2048 -### twiClockFreq_t -##### Description -I2C bus speed. -##### Values -- extEEPROM::twiClock100kHz -- extEEPROM::twiClock400kHz - -## Constructor ## -### extEEPROM(eeprom_size_t devCap, byte nDev, unsigned int pgSize, byte busAddr) -##### Description -Instantiates an external EEPROM object. -##### Syntax -`extEEPROM myEEPROM(eeprom_size_t devCap, byte nDev, unsigned int pgSize, byte busAddr);` -##### Parameters -**devCap** *(eeprom_size_t)*: The size of one EEPROM device in k-bits. Choose a value from the eeprom_size_t enumeration above. -**nDev** *(byte)*: The number of EEPROM devices on the bus. Note that if there are multiple EEPROM devices on the bus, they must be identical and each must have its address pins strapped properly. -**pgSize** *(unsigned int)*: The EEPROM page size in bytes. Consult the datasheet if you are unsure of the page size. -**busAddr** *(byte)*: The base I2C bus address for the EEPROM(s). 0x50 is a common value and this parameter can be omitted, in which case 0x50 will be used as the default. -##### Example -```c++ -extEEPROM myEEPROM(kbits_256, 2, 64); //two 24LC256 EEPROMS on the bus -extEEPROM oddEEPROM(kbits_8, 1, 16, 0x42); //an EEPROM with a non-standard I2C address -``` - -## Methods ## -### begin(twiClockFreq_t freq, TwoWire *_comm) -##### Description -Initializes the library. Call this method once in the setup code. begin() does a dummy I/O so that the user may interrogate the return status to ensure the EEPROM is operational. -##### Syntax -`myEEPROM.begin(twiClockFreq_t freq);` -or -`myEEPROM.begin(twiClockFreq_t freq, TwoWire *_comm);` -##### Parameters -**freq** *(twiClockFreq_t)*: The desired I2C bus speed, `extEEPROM::twiClock100kHz` or `extEEPROM::twiClock400kHz`. Can be omitted in which case it will default to `twiClock100kHz`. -**NOTE:** When using 400kHz, if there are other devices on the bus they must all support a 400kHz bus speed. **Secondly**, the other devices should be initialized first, as other libraries may not support adjusting the bus speed. To ensure the desired speed is set, call the extEEPROM.begin() function *after* initializing all other I2C devices. - -**_comm** *(TwoWire * )*: The Used I2C TwoWire channel . Can be omitted in which case it will default to the first Arduino I2C channel `Wire`. If another of the possible I2C channel is used its pointer shall be passed as parameter. -**NOTE:** If another I2C channel is unse, and not the default one, the first parameters **freq** MUST be defined. -##### Returns -I2C I/O status, zero if successful *(byte)*. See the [Arduino Wire.endTransmission() function](http://arduino.cc/en/Reference/WireEndTransmission) for a description of other return codes. - -##### Examples -```c++ -extEEPROM myEEPROM(kbits_256, 2, 64); -byte i2cStat = myEEPROM.begin(extEEPROM::twiClock400kHz); -if ( i2cStat != 0 ) { - //there was a problem -} -``` -##### Use of other I2C channel -```c++ -extEEPROM myEEPROM(kbits_256, 2, 64); -byte i2cStat = myEEPROM.begin(extEEPROM::twiClock400kHz, &Wire1); -if ( i2cStat != 0 ) { - //there was a problem -} -``` -### write(unsigned long addr, byte *values, unsigned int nBytes) -##### Description -Write one or more bytes to external EEPROM. -##### Syntax -`myEEPROM.write(unsigned long addr, byte* values, byte nBytes);` -##### Parameters -**addr** *(unsigned long)*: The beginning EEPROM location to write. -**values** _(byte*)_: Pointer to an array containing the data to write. -**nBytes** *(unsigned int)*: The number of bytes to write. -##### Returns -I2C I/O status, zero if successful *(byte)*. See the [Arduino Wire.endTransmission() function](http://arduino.cc/en/Reference/WireEndTransmission) for a description of other return codes. Returns a status of EEPROM_ADDR_ERR if the I/O would extend past the top of the EEPROM address space. -##### Example -```c++ -byte myData[10]; -//write 10 bytes starting at location 42 -byte i2cStat = myEEPROM.write(42, &data, 10); -if ( i2cStat != 0 ) { - //there was a problem - if ( i2cStat == EEPROM_ADDR_ERR) { - //bad address - } - else { - //some other I2C error - } -} -``` -### write(unsigned long addr, byte value) -##### Description -Writes a single byte to external EEPROM. -##### Syntax -`myEEPROM.write(unsigned long addr, byte value);` -##### Parameters -**addr** *(unsigned long)*: The EEPROM location to write. -**values** _(byte)_: The value to write. -##### Returns -Same as multiple-byte write() above. -##### Example -```c++ -//write the value 16 to EEPROM location 314. -byte i2cStat = myEEPROM.write(314, 16); -``` -### read(unsigned long addr, byte *values, unsigned int nBytes) -##### Description -Reads one or more bytes from external EEPROM into an array supplied by the caller. -##### Syntax -`myEEPROM.read(unsigned long addr, byte *values, byte nBytes);` -##### Parameters -**addr** *(unsigned long)*: The beginning EEPROM location to read from. -**values** _(byte*)_: Pointer to an array to receive the data. -**nBytes** *(unsigned int)*: The number of bytes to read. -##### Returns -I2C I/O status, zero if successful *(byte)*. See the [Arduino Wire.endTransmission() function](http://arduino.cc/en/Reference/WireEndTransmission) for a description of other return codes. Returns a status of EEPROM_ADDR_ERR if the I/O would extend past the top of the EEPROM address space. -##### Example -```c++ -byte myData[10]; -//read 10 bytes starting at location 42 -byte i2cStat = myEEPROM.read(42, &data, 10); -if ( i2cStat != 0 ) { - //there was a problem - if ( i2cStat == EEPROM_ADDR_ERR) { - //bad address - } - else { - //some other I2C error - } -} -``` -### read(unsigned long addr) -##### Description -Reads a single byte from external EEPROM. -##### Syntax -`myEEPROM.read(unsigned long addr);` -##### Parameters -**addr** *(unsigned long)*: The EEPROM location to read from. -##### Returns -The data read from EEPROM or an error code *(int)*. To distinguish error values from valid data, error values are returned as negative numbers. See the [Arduino Wire.endTransmission() function](http://arduino.cc/en/Reference/WireEndTransmission) for a description of return codes. Returns a status of EEPROM_ADDR_ERR if the I/O would extend past the top of the EEPROM address space. -##### Example -```c++ -int myData; -//read a byte from location 42 -int readValue = myEEPROM.read(42); -if ( readValue < 0 ) { - //there was a problem - if ( -readValue == EEPROM_ADDR_ERR) { - //bad address - } - else { - //some other I2C error - } -} -else { - //data read ok -} -``` - -"Arduino External EEPROM Library" by Jack Christensen is licensed under [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/). -![CC BY-SA](http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by-sa.png) diff --git a/lib/MySensors/drivers/extEEPROM/examples/eepromReadWrite/eepromReadWrite.ino b/lib/MySensors/drivers/extEEPROM/examples/eepromReadWrite/eepromReadWrite.ino deleted file mode 100644 index f260c39a..00000000 --- a/lib/MySensors/drivers/extEEPROM/examples/eepromReadWrite/eepromReadWrite.ino +++ /dev/null @@ -1,209 +0,0 @@ -/* - Copyright (c) 2014 Arduino. All right reserved. - - 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 "extEEPROM.h" - -extEEPROM myEEPROM(kbits_256, 1, 64, 0x57); - -void setup(void) -{ - SerialUSB.begin(115200); - while (!SerialUSB) { - ; - } - - byte i2cStat = myEEPROM.begin(myEEPROM.twiClock100kHz); - if ( i2cStat != 0 ) { - SerialUSB.println(F("I2C Problem")); - } - - SerialUSB.println( - F("EEPROM Memory commands: read:(a)(l)(r) , write:(a)(d)(w), next read data (n)")); - SerialUSB.println(F("- Commands TO PRESS:")); - SerialUSB.println(F("\t a : memory address to read / write")); - SerialUSB.println(F("\t d : data to write")); - SerialUSB.println(F("\t l : data to write")); - SerialUSB.println(F("\t r : read command")); - SerialUSB.println(F("\t w : write command")); -} - -unsigned long address = 0; -const unsigned int maxDataSize = 1024; //0x8000; // 32 k bytes (32768 = 0x8000) = 256 kbits - -byte data[maxDataSize] = {'p', 'i', 'p', 'p', 'o'}; -unsigned int dataSize = 5; - -void eprom_read_write(bool write) -{ - byte i2cStat = 0; - if (write) { - i2cStat = myEEPROM.write(address, data, dataSize); - } else { - memset(data, 0, maxDataSize); - i2cStat = myEEPROM.read(address, data, dataSize); - } - if ( i2cStat != 0 ) { - //there was a problem - SerialUSB.print(F("I2C Problem: ")); - if ( i2cStat == EEPROM_ADDR_ERR) { - SerialUSB.println(F("Wrong address")); - } else { - SerialUSB.print(F("I2C error: ")); - SerialUSB.print(i2cStat); - SerialUSB.println(F("")); - } - } -} - - -void parse(char inChar) -{ - const char addr_len = 5; - char addr_char[addr_len] = ""; - const char data_len = 3; - char data_char[data_len] = ""; - char size_char[data_len] = ""; - char inc = 0, i = 0, j = 0; - - switch (inChar) { - case 'a': - SerialUSB.print(F("Insert Address as 4 Hex chars (without '0x'): ")); - - while (i < 4) { - while (SerialUSB.available() <= 0) - ; - inc = SerialUSB.read(); - - if (inc == 'q') { - return; - } - - addr_char[i] = inc; - ++i; - } - address = (unsigned long)strtol(addr_char, NULL, 16); - SerialUSB.println(address); - break; - - case 'd': - SerialUSB.print(F("Insert Hex data sequence (without '0x'), return to enter: ")); - memset(data, 0, maxDataSize); - while (true) { - while (SerialUSB.available() <= 0) - ; - inc = SerialUSB.read(); - if (inc == 'q') { - return; - } - if (inc == '\r' || inc == '\n') { - break; - } - - if (inc >= 'a' && inc <= 'f') { - data[j] += inc - 'a' + 10; - } else if (inc >= 'A' && inc <= 'F') { - data[j] += inc - 'A' + 10; - } else if (inc >= '0' && inc <= '9') { - data[j] += inc - '0'; - } else { - return; - } - - if (i % 2) { - j++; - } else { - data[j] = data[j] << 4; - } - i++; - } - dataSize = j; - SerialUSB.println(dataSize); - SerialUSB.println(F("")); - break; - case 'l': - SerialUSB.print(F("Insert data len as 2 Hex chars (without '0x'): ")); - while (i < 2) { - while (SerialUSB.available() <= 0) - ; - inc = SerialUSB.read(); - if (inc == 'q') { - return; - } - - size_char[i] = inc; - ++i; - if (inc == '\n') { - return; - } - } - - dataSize = (unsigned int)strtol(size_char, NULL, 16); - SerialUSB.println(dataSize); - break; - - - case 'n': - address += dataSize; - /* FALLTHROUGH */ - case 'r': - SerialUSB.print(F("reading address: ")); - SerialUSB.println(address, HEX); - - eprom_read_write(false); - for (i = 0; i < dataSize ; ++i) { - SerialUSB.print(data[i], HEX); - SerialUSB.print(F(" ")); - } - SerialUSB.println(); - - break; - - case 'w': - SerialUSB.print(F("writing at address: ")); - SerialUSB.print(address, HEX); - SerialUSB.print(F(", len: ")); - SerialUSB.println(address, dataSize); - for (i = 0; i < dataSize ; ++i) { - SerialUSB.print(data[i], HEX); - SerialUSB.print(F(" ")); - } - eprom_read_write(true); - SerialUSB.println(); - - break; - case 'T': - SerialUSB.println(F("Memory test: writing and verifying the whole memory")); - break; - - default: - break; - } -} - - -void loop(void) -{ - if (SerialUSB.available() > 0) { - char inChar = SerialUSB.read(); - SerialUSB.print(inChar); - parse(inChar); - } - - delay(10); -} - diff --git a/lib/MySensors/drivers/extEEPROM/examples/eepromTest/eepromTest.ino b/lib/MySensors/drivers/extEEPROM/examples/eepromTest/eepromTest.ino deleted file mode 100644 index 079daca0..00000000 --- a/lib/MySensors/drivers/extEEPROM/examples/eepromTest/eepromTest.ino +++ /dev/null @@ -1,176 +0,0 @@ -//Test extEEPROM library. -//Writes the EEPROM full of 32-bit integers and reads them back to verify. -//Wire a button from digital pin 6 to ground, this is used as a start button -//so the sketch doesn't do unnecessary EEPROM writes every time it's reset. -//Jack Christensen 09Jul2014 -//Paolo Paolucci 17Mar2016 (fix 28Jun2017) - -#include //https://github.com/PaoloP74/extEEPROM - -//One 24LC256 EEPROMs on the bus -const uint32_t totalKBytes = 32; //for read and write test functions -extEEPROM eep(kbits_256, 1, 64); //device size, number of devices, page size - -const uint8_t btnStart = 6; //start button - -void setup(void) -{ - pinMode(btnStart, INPUT_PULLUP); - Serial.begin(115200); - uint8_t eepStatus = eep.begin(eep.twiClock400kHz); //go fast! - if (eepStatus) { - Serial.print(F("extEEPROM.begin() failed, status = ")); - Serial.println(eepStatus); - while (1); - } - - Serial.println(F("Press button to start...")); - while (digitalRead(btnStart) == HIGH) { - delay(10); //wait for button push - } - - uint8_t chunkSize = - 64; //this can be changed, but must be a multiple of 4 since we're writing 32-bit integers - // eeErase(chunkSize, 0, totalKBytes * 1024 - 1); - eeWrite(chunkSize); - eeRead(chunkSize); - - dump(0, 32); //the first 32 bytes - dump(32256, 64); //the last 64 bytes - //dump(32512, 64); //across the device boundary - //dump(65520, 16); //the last 16 bytes -} - -void loop(void) -{ -} - -//write test data (32-bit integers) to eeprom, "chunk" bytes at a time -void eeWrite(uint8_t chunk) -{ - chunk &= 0xFC; //force chunk to be a multiple of 4 - uint8_t data[chunk]; - uint32_t val = 0; - Serial.println(F("Writing...")); - uint32_t msStart = millis(); - - for (uint32_t addr = 0; addr < totalKBytes * 1024; addr += chunk) { - if ( (addr & 0xFFF) == 0 ) { - Serial.println(addr); - } - for (uint8_t c = 0; c < chunk; c += 4) { - data[c + 0] = val >> 24; - data[c + 1] = val >> 16; - data[c + 2] = val >> 8; - data[c + 3] = val; - ++val; - } - eep.write(addr, data, chunk); - } - uint32_t msLapse = millis() - msStart; - Serial.print(F("Write lapse: ")); - Serial.print(msLapse); - Serial.println(F(" ms")); -} - -//read test data (32-bit integers) from eeprom, "chunk" bytes at a time -void eeRead(uint8_t chunk) -{ - chunk &= 0xFC; //force chunk to be a multiple of 4 - uint8_t data[chunk]; - uint32_t val = 0, testVal; - Serial.println(F("Reading...")); - uint32_t msStart = millis(); - - for (uint32_t addr = 0; addr < totalKBytes * 1024; addr += chunk) { - if ( (addr & 0xFFF) == 0 ) { - Serial.println(addr); - } - eep.read(addr, data, chunk); - for (uint8_t c = 0; c < chunk; c += 4) { - testVal = ((uint32_t)data[c + 0] << 24) + ((uint32_t)data[c + 1] << 16) + (( - uint32_t)data[c + 2] << 8) + (uint32_t)data[c + 3]; - if (testVal != val) { - Serial.print(F("Error @ addr ")); - Serial.print(addr + c); - Serial.print(F(" Expected ")); - Serial.print(val); - Serial.print(F(" Read ")); - Serial.print(testVal); - Serial.print(F(" 0x")); - Serial.println(testVal, HEX); - } - ++val; - } - } - uint32_t msLapse = millis() - msStart; - Serial.print(F("Last value: ")); - Serial.print(val); - Serial.print(F(" Read lapse: ")); - Serial.print(msLapse); - Serial.println(F(" ms")); -} - -//write 0xFF to eeprom, "chunk" bytes at a time -void eeErase(uint8_t chunk, uint32_t startAddr, uint32_t endAddr) -{ - chunk &= 0xFC; //force chunk to be a multiple of 4 - uint8_t data[chunk]; - Serial.println(F("Erasing...")); - for (int i = 0; i < chunk; i++) { - data[i] = 0xFF; - } - uint32_t msStart = millis(); - - for (uint32_t a = startAddr; a <= endAddr; a += chunk) { - if ( (a & 0xFFF) == 0 ) { - Serial.println(a); - } - eep.write(a, data, chunk); - } - uint32_t msLapse = millis() - msStart; - Serial.print(F("Erase lapse: ")); - Serial.print(msLapse); - Serial.print(F(" ms")); -} - -//dump eeprom contents, 16 bytes at a time. -//always dumps a multiple of 16 bytes. -void dump(uint32_t startAddr, uint32_t nBytes) -{ - Serial.print(F("EEPROM DUMP 0x")); - Serial.print(startAddr, HEX); - Serial.print(F(" 0x")); - Serial.print(nBytes, HEX); - Serial.print(F(" ")); - Serial.print(startAddr); - Serial.print(F(" ")); - Serial.println(nBytes); - uint32_t nRows = (nBytes + 15) >> 4; - - uint8_t d[16]; - for (uint32_t r = 0; r < nRows; r++) { - uint32_t a = startAddr + 16 * r; - eep.read(a, d, 16); - Serial.print(F("0x")); - if ( a < 16 * 16 * 16 ) { - Serial.print(F("0")); - } - if ( a < 16 * 16 ) { - Serial.print(F("0")); - } - if ( a < 16 ) { - Serial.print(F("0")); - } - Serial.print(a, HEX); - Serial.print(F(" ")); - for ( int c = 0; c < 16; c++ ) { - if ( d[c] < 16 ) { - Serial.print(F("0")); - Serial.print(d[c], HEX); - Serial.print( c == 7 ? " " : " "); - } - } - Serial.println(F("")); - } -} diff --git a/lib/MySensors/drivers/extEEPROM/examples/eepromTest_Wire1/eepromTest_Wire1.ino b/lib/MySensors/drivers/extEEPROM/examples/eepromTest_Wire1/eepromTest_Wire1.ino deleted file mode 100644 index 44a8f8fe..00000000 --- a/lib/MySensors/drivers/extEEPROM/examples/eepromTest_Wire1/eepromTest_Wire1.ino +++ /dev/null @@ -1,233 +0,0 @@ -//Test extEEPROM library. -//Writes the EEPROM full of 32-bit integers and reads them back to verify. -//Wire a button from digital pin 6 to ground, this is used as a start button -//so the sketch doesn't do unnecessary EEPROM writes every time it's reset. -//Jack Christensen 09Jul2014 -//Paolo Paolucci 17Mar2016 (fix 28Jun2017) -//Mik 03Jan2017 (configured Library to use the Wire1 as I2C channel) - -#include //https://github.com/PaoloP74/extEEPROM - -//One 24LC256 EEPROMs on the bus -const uint32_t totalKBytes = 32; //for read and write test functions -extEEPROM eep(kbits_256, 1, 64, 0x57); //device size, number of devices, page size - -const uint8_t btnStart = 6; //start button - -void setup(void) -{ - uint8_t eepStatus; - pinMode(btnStart, INPUT_PULLUP); - Serial.begin(115200); - while (!SerialUSB) {} - - bool channelInsert = false; - Serial.println(F("Select the number of Wire channel use the eeprom")); - Serial.println(F("0 = Wire")); - Serial.println(F("1 = Wire1")); - Serial.println(F("....")); - Serial.println(F("x = WIRE_INTERFACES_COUNT")); - - do { - if (Serial.available()) { - char I2Cchannel = Serial.read(); - - // only number that are less than WIRE_INTERFACES_COUNT are allowed - if ((I2Cchannel > '0') && (I2Cchannel < ('0' + WIRE_INTERFACES_COUNT))) { - channelInsert = true; - } - - switch ((I2Cchannel - '0')) { - - case 0: - Serial.println(F("Using the default Wire interface")); - eepStatus = eep.begin(eep.twiClock400kHz); //go fast! - break; - - case 1: - Serial.println(F("Using the Wire1 interface")); - eepStatus = eep.begin(eep.twiClock400kHz, &Wire1); //go fast! - break; - - /* - Uncomment till the number of WIRE_INTERFACES_COUNT of your Arduino board - case 2: - Serial.println(F("Using the Wire2 interface")); - eepStatus = eep.begin(eep.twiClock400kHz, &Wire2); //go fast! - break; - - case 3: - Serial.println(F("Using the Wire3 interface")); - eepStatus = eep.begin(eep.twiClock400kHz, &Wire3); //go fast! - break; - - case 4: - Serial.println(F("Using the Wire4 interface")); - eepStatus = eep.begin(eep.twiClock400kHz, &Wire4); //go fast! - break; - - case 5: - Serial.println(F("Using the Wire5 interface")); - eepStatus = eep.begin(eep.twiClock400kHz, &Wire5); //go fast! - break;*/ - - default: - Serial.println(F("A wrong channel has been inserted (Arduino manage max 5)")); - break; - } - } - } while (!channelInsert); - - if (eepStatus) { - Serial.print(F("extEEPROM.begin() failed, status = ")); - Serial.println(eepStatus); - while (1); - } - - Serial.println(F("Started !!")); - - uint8_t chunkSize = - 64; //this can be changed, but must be a multiple of 4 since we're writing 32-bit integers - // eeErase(chunkSize, 0, totalKBytes * 1024 - 1); - eeWrite(chunkSize); - eeRead(chunkSize); - - dump(0, 32); //the first 32 bytes - dump(32256, 64); //the last 64 bytes - //dump(32512, 64); //across the device boundary - //dump(65520, 16); //the last 16 bytes -} - -void loop(void) -{ -} - -//write test data (32-bit integers) to eeprom, "chunk" bytes at a time -void eeWrite(uint8_t chunk) -{ - chunk &= 0xFC; //force chunk to be a multiple of 4 - uint8_t data[chunk]; - uint32_t val = 0; - Serial.println(F("Writing...")); - uint32_t msStart = millis(); - - for (uint32_t addr = 0; addr < totalKBytes * 1024; addr += chunk) { - if ( (addr & 0xFFF) == 0 ) { - Serial.println(addr); - } - for (uint8_t c = 0; c < chunk; c += 4) { - data[c + 0] = val >> 24; - data[c + 1] = val >> 16; - data[c + 2] = val >> 8; - data[c + 3] = val; - ++val; - } - eep.write(addr, data, chunk); - } - uint32_t msLapse = millis() - msStart; - Serial.print(F("Write lapse: ")); - Serial.print(msLapse); - Serial.println(F(" ms")); -} - -//read test data (32-bit integers) from eeprom, "chunk" bytes at a time -void eeRead(uint8_t chunk) -{ - chunk &= 0xFC; //force chunk to be a multiple of 4 - uint8_t data[chunk]; - uint32_t val = 0, testVal; - Serial.println(F("Reading...")); - uint32_t msStart = millis(); - - for (uint32_t addr = 0; addr < totalKBytes * 1024; addr += chunk) { - if ( (addr & 0xFFF) == 0 ) { - Serial.println(addr); - } - eep.read(addr, data, chunk); - for (uint8_t c = 0; c < chunk; c += 4) { - testVal = ((uint32_t)data[c + 0] << 24) + ((uint32_t)data[c + 1] << 16) + (( - uint32_t)data[c + 2] << 8) + (uint32_t)data[c + 3]; - if (testVal != val) { - Serial.print(F("Error @ addr ")); - Serial.print(addr + c); - Serial.print(F(" Expected ")); - Serial.print(val); - Serial.print(F(" Read ")); - Serial.print(testVal); - Serial.print(F(" 0x")); - Serial.println(testVal, HEX); - } - ++val; - } - } - uint32_t msLapse = millis() - msStart; - Serial.print(F("Last value: ")); - Serial.print(val); - Serial.print(F(" Read lapse: ")); - Serial.print(msLapse); - Serial.println(F(" ms")); -} - -//write 0xFF to eeprom, "chunk" bytes at a time -void eeErase(uint8_t chunk, uint32_t startAddr, uint32_t endAddr) -{ - chunk &= 0xFC; //force chunk to be a multiple of 4 - uint8_t data[chunk]; - Serial.println(F("Erasing...")); - for (int i = 0; i < chunk; i++) { - data[i] = 0xFF; - } - uint32_t msStart = millis(); - - for (uint32_t a = startAddr; a <= endAddr; a += chunk) { - if ( (a & 0xFFF) == 0 ) { - Serial.println(a); - } - eep.write(a, data, chunk); - } - uint32_t msLapse = millis() - msStart; - Serial.print(F("Erase lapse: ")); - Serial.print(msLapse); - Serial.print(F(" ms")); -} - -//dump eeprom contents, 16 bytes at a time. -//always dumps a multiple of 16 bytes. -void dump(uint32_t startAddr, uint32_t nBytes) -{ - Serial.print(F("EEPROM DUMP 0x")); - Serial.print(startAddr, HEX); - Serial.print(F(" 0x")); - Serial.print(nBytes, HEX); - Serial.print(F(" ")); - Serial.print(startAddr); - Serial.print(F(" ")); - Serial.println(nBytes); - uint32_t nRows = (nBytes + 15) >> 4; - - uint8_t d[16]; - for (uint32_t r = 0; r < nRows; r++) { - uint32_t a = startAddr + 16 * r; - eep.read(a, d, 16); - Serial.print(F("0x")); - if ( a < 16 * 16 * 16 ) { - Serial.print(F("0")); - } - if ( a < 16 * 16 ) { - Serial.print(F("0")); - } - if ( a < 16 ) { - Serial.print(F("0")); - } - Serial.print(a, HEX); - Serial.print(F(" ")); - for ( int c = 0; c < 16; c++ ) { - if ( d[c] < 16 ) { - Serial.print(F("0")); - Serial.print(d[c], HEX); - Serial.print( c == 7 ? " " : " "); - } - } - Serial.println(F("")); - } -} diff --git a/lib/MySensors/drivers/extEEPROM/extEEPROM.cpp b/lib/MySensors/drivers/extEEPROM/extEEPROM.cpp deleted file mode 100644 index 5b56c17b..00000000 --- a/lib/MySensors/drivers/extEEPROM/extEEPROM.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/*-----------------------------------------------------------------------------* - * extEEPROM.cpp - Arduino library to support external I2C EEPROMs. * - * * - * This library will work with most I2C serial EEPROM chips between 2k bits * - * and 2048k bits (2M bits) in size. Multiple EEPROMs on the bus are supported * - * as a single address space. I/O across block, page and device boundaries * - * is supported. Certain assumptions are made regarding the EEPROM * - * device addressing. These assumptions should be true for most EEPROMs * - * but there are exceptions, so read the datasheet and know your hardware. * - * * - * The library should also work for EEPROMs smaller than 2k bits, assuming * - * that there is only one EEPROM on the bus and also that the user is careful * - * to not exceed the maximum address for the EEPROM. * - * * - * Library tested with: * - * Microchip 24AA02E48 (2k bit) * - * 24xx32 (32k bit, thanks to Richard M) * - * Microchip 24LC256 (256k bit) * - * Microchip 24FC1026 (1M bit, thanks to Gabriele B on the Arduino forum) * - * ST Micro M24M02 (2M bit) * - * * - * Library will NOT work with Microchip 24xx1025 as its control byte does not * - * conform to the following assumptions. * - * * - * Device addressing assumptions: * - * 1. The I2C address sequence consists of a control byte followed by one * - * address byte (for EEPROMs <= 16k bits) or two address bytes (for * - * EEPROMs > 16k bits). * - * 2. The three least-significant bits in the control byte (excluding the R/W * - * bit) comprise the three most-significant bits for the entire address * - * space, i.e. all chips on the bus. As such, these may be chip-select * - * bits or block-select bits (for individual chips that have an internal * - * block organization), or a combination of both (in which case the * - * block-select bits must be of lesser significance than the chip-select * - * bits). * - * 3. Regardless of the number of bits needed to address the entire address * - * space, the three most-significant bits always go in the control byte. * - * Depending on EEPROM device size, this may result in one or more of the * - * most significant bits in the I2C address bytes being unused (or "don't * - * care"). * - * 4. An EEPROM contains an integral number of pages. * - * * - * To use the extEEPROM library, the Arduino Wire library must also * - * be included. * - * * - * Jack Christensen 23Mar2013 v1 * - * 29Mar2013 v2 - Updated to span page boundaries (and therefore also * - * device boundaries, assuming an integral number of pages per device) * - * 08Jul2014 v3 - Generalized for 2kb - 2Mb EEPROMs. * - * * - * Paolo Paolucci 22-10-2015 v3.1 * - * 09-01-2016 v3.2 Add update function. * - * * - * External EEPROM Library by Jack Christensen is licensed under CC BY-SA 4.0, * - * http://creativecommons.org/licenses/by-sa/4.0/ * - *-----------------------------------------------------------------------------*/ - -#include "extEEPROM.h" - -// workaround, BUFFER_LENGTH is not defined in Wire.h for SAMD controllers -#ifndef BUFFER_LENGTH -#define BUFFER_LENGTH 32 -#endif - -// Constructor. -// - deviceCapacity is the capacity of a single EEPROM device in -// kilobits (kb) and should be one of the values defined in the -// eeprom_size_t enumeration in the extEEPROM.h file. (Most -// EEPROM manufacturers use kbits in their part numbers.) -// - nDevice is the number of EEPROM devices on the I2C bus (all must -// be identical). -// - pageSize is the EEPROM's page size in bytes. -// - eepromAddr is the EEPROM's I2C address and defaults to 0x50 which is common. -extEEPROM::extEEPROM(eeprom_size_t deviceCapacity, byte nDevice, unsigned int pageSize, - uint8_t eepromAddr) -{ - communication = NULL; - _dvcCapacity = deviceCapacity; - _nDevice = nDevice; - _pageSize = pageSize; - _eepromAddr = eepromAddr; - _totalCapacity = _nDevice * _dvcCapacity * 1024UL / 8; - _nAddrBytes = deviceCapacity > kbits_16 ? 2 : - 1; //two address bytes needed for eeproms > 16kbits - - //determine the bitshift needed to isolate the chip select bits from the address to put into the control byte - uint16_t kb = _dvcCapacity; - if ( kb <= kbits_16 ) { - _csShift = 8; - } else if ( kb >= kbits_512 ) { - _csShift = 16; - } else { - kb >>= 6; - _csShift = 12; - while ( kb >= 1 ) { - ++_csShift; - kb >>= 1; - } - } -} - -//initialize the I2C bus and do a dummy write (no data sent) -//to the device so that the caller can determine whether it is responding. -//when using a 400kHz bus speed and there are multiple I2C devices on the -//bus (other than EEPROM), call extEEPROM::begin() after any initialization -//calls for the other devices to ensure the intended I2C clock speed is set. -byte extEEPROM::begin(twiClockFreq_t twiFreq, TwoWire *_comm) -{ - communication = _comm; - communication->begin(); - communication->setClock(twiFreq); - communication->beginTransmission(_eepromAddr); - if (_nAddrBytes == 2) { - communication->write((byte)0); //high addr byte - } - communication->write((byte)0); //low addr byte - return communication->endTransmission(); -} - -//Write bytes to external EEPROM. -//If the I/O would extend past the top of the EEPROM address space, -//a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status -//from the Arduino Wire library is passed back through to the caller. -byte extEEPROM::write(unsigned long addr, byte *values, unsigned int nBytes) -{ - uint8_t txStatus = 0; //transmit status - - if (addr + nBytes > _totalCapacity) { //will this write go past the top of the EEPROM? - return EEPROM_ADDR_ERR; //yes, tell the caller - } - - while (nBytes > 0) { - const uint16_t nPage = _pageSize - ( addr & (_pageSize - 1) ); - //find min(nBytes, nPage, BUFFER_LENGTH) -- BUFFER_LENGTH is defined in the Wire library. - uint16_t nWrite = nBytes < nPage ? nBytes : nPage; - nWrite = BUFFER_LENGTH - _nAddrBytes < nWrite ? BUFFER_LENGTH - _nAddrBytes : nWrite; - const uint8_t ctrlByte = _eepromAddr | (byte) (addr >> _csShift); - communication->beginTransmission(ctrlByte); - if (_nAddrBytes == 2) { - communication->write( (byte) (addr >> 8) ); //high addr byte - } - communication->write( (byte) addr ); //low addr byte - communication->write(values, nWrite); - txStatus = communication->endTransmission(); - if (txStatus != 0) { - return txStatus; - } - - //wait up to 50ms for the write to complete - for (uint8_t i=100; i; --i) { - delayMicroseconds(500); //no point in waiting too fast - communication->beginTransmission(ctrlByte); - if (_nAddrBytes == 2) { - communication->write((byte)0); //high addr byte - } - communication->write((byte)0); //low addr byte - txStatus = communication->endTransmission(); - if (txStatus == 0) { - break; - } - } - if (txStatus != 0) { - return txStatus; - } - - addr += nWrite; //increment the EEPROM address - values += nWrite; //increment the input data pointer - nBytes -= nWrite; //decrement the number of bytes left to write - } - return txStatus; -} - -//Read bytes from external EEPROM. -//If the I/O would extend past the top of the EEPROM address space, -//a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status -//from the Arduino Wire library is passed back through to the caller. -byte extEEPROM::read(unsigned long addr, byte *values, unsigned int nBytes) -{ - if (addr + nBytes > _totalCapacity) { //will this read take us past the top of the EEPROM? - return EEPROM_ADDR_ERR; //yes, tell the caller - } - - while (nBytes > 0) { - const uint16_t nPage = _pageSize - ( addr & (_pageSize - 1) ); - uint16_t nRead = nBytes < nPage ? nBytes : nPage; - nRead = BUFFER_LENGTH < nRead ? BUFFER_LENGTH : nRead; - byte ctrlByte = _eepromAddr | (byte) (addr >> _csShift); - communication->beginTransmission(ctrlByte); - if (_nAddrBytes == 2) { - communication->write( (byte) (addr >> 8) ); //high addr byte - } - communication->write( (byte) addr ); //low addr byte - const byte rxStatus = communication->endTransmission(); - if (rxStatus != 0) { - return rxStatus; //read error - } - - communication->requestFrom(ctrlByte, nRead); - for (byte i=0; iread(); - } - - addr += nRead; //increment the EEPROM address - values += nRead; //increment the input data pointer - nBytes -= nRead; //decrement the number of bytes left to write - } - return 0; -} - -//Write a single byte to external EEPROM. -//If the I/O would extend past the top of the EEPROM address space, -//a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status -//from the Arduino Wire library is passed back through to the caller. -byte extEEPROM::write(unsigned long addr, byte value) -{ - return write(addr, &value, 1); -} - -//Read a single byte from external EEPROM. -//If the I/O would extend past the top of the EEPROM address space, -//a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status -//from the Arduino Wire library is passed back through to the caller. -//To distinguish error values from valid data, error values are returned as negative numbers. -int extEEPROM::read(unsigned long addr) -{ - uint8_t data; - int ret; - - ret = read(addr, &data, 1); - return ret == 0 ? data : -ret; -} - -//Update bytes to external EEPROM. -//For I2C errors, the status from the Arduino Wire library is passed back through to the caller. -byte extEEPROM::update(unsigned long addr, byte *values, unsigned int nBytes) -{ - for (unsigned int i = 0; i < nBytes; i++) { - const uint8_t newValue = values[i]; - if (newValue != read(addr + i)) { - write(addr + i, newValue); - } - } - return true; -} - -//Update a single byte to external EEPROM. -//For I2C errors, the status from the Arduino Wire library is passed back through to the caller. -byte extEEPROM::update(unsigned long addr, byte value) -{ - return (value != read(addr) ? write(addr, &value, 1) : 0); -} - -//For I2C errors, the status from the Arduino Wire library is passed back through to the caller. -unsigned long extEEPROM::length( void ) -{ - return _totalCapacity * 8; -} diff --git a/lib/MySensors/drivers/extEEPROM/extEEPROM.h b/lib/MySensors/drivers/extEEPROM/extEEPROM.h deleted file mode 100644 index 42f43dc7..00000000 --- a/lib/MySensors/drivers/extEEPROM/extEEPROM.h +++ /dev/null @@ -1,131 +0,0 @@ -/*-----------------------------------------------------------------------------* - * extEEPROM.h - Arduino library to support external I2C EEPROMs. * - * * - * This library will work with most I2C serial EEPROM chips between 2k bits * - * and 2048k bits (2M bits) in size. Multiple EEPROMs on the bus are supported * - * as a single address space. I/O across block, page and device boundaries * - * is supported. Certain assumptions are made regarding the EEPROM * - * device addressing. These assumptions should be true for most EEPROMs * - * but there are exceptions, so read the datasheet and know your hardware. * - * * - * The library should also work for EEPROMs smaller than 2k bits, assuming * - * that there is only one EEPROM on the bus and also that the user is careful * - * to not exceed the maximum address for the EEPROM. * - * * - * Library tested with: * - * Microchip 24AA02E48 (2k bit) * - * 24xx32 (32k bit, thanks to Richard M) * - * Microchip 24LC256 (256k bit) * - * Microchip 24FC1026 (1M bit, thanks to Gabriele B on the Arduino forum) * - * ST Micro M24M02 (2M bit) * - * * - * Library will NOT work with Microchip 24xx1025 as its control byte does not * - * conform to the following assumptions. * - * * - * Device addressing assumptions: * - * 1. The I2C address sequence consists of a control byte followed by one * - * address byte (for EEPROMs <= 16k bits) or two address bytes (for * - * EEPROMs > 16k bits). * - * 2. The three least-significant bits in the control byte (excluding the R/W * - * bit) comprise the three most-significant bits for the entire address * - * space, i.e. all chips on the bus. As such, these may be chip-select * - * bits or block-select bits (for individual chips that have an internal * - * block organization), or a combination of both (in which case the * - * block-select bits must be of lesser significance than the chip-select * - * bits). * - * 3. Regardless of the number of bits needed to address the entire address * - * space, the three most-significant bits always go in the control byte. * - * Depending on EEPROM device size, this may result in one or more of the * - * most significant bits in the I2C address bytes being unused (or "don't * - * care"). * - * 4. An EEPROM contains an integral number of pages. * - * * - * To use the extEEPROM library, the Arduino Wire library must also * - * be included. * - * * - * Jack Christensen 23Mar2013 v1 * - * 29Mar2013 v2 - Updated to span page boundaries (and therefore also * - * device boundaries, assuming an integral number of pages per device) * - * 08Jul2014 v3 - Generalized for 2kb - 2Mb EEPROMs. * - * * - * Paolo Paolucci 22-10-2015 v3.2 * - * 09-01-2016 v3.2 Add update function. * - * * - * External EEPROM Library by Jack Christensen is licensed under CC BY-SA 4.0, * - * http://creativecommons.org/licenses/by-sa/4.0/ * - *-----------------------------------------------------------------------------*/ - -/* - * tekka 2018: - * Re-implementing extEEPROM::update(unsigned long addr, byte value); - */ -#ifndef extEEPROM_h -#define extEEPROM_h - -#include -#include - -//EEPROM size in kilobits. EEPROM part numbers are usually designated in k-bits. -enum eeprom_size_t { - kbits_2 = 2, - kbits_4 = 4, - kbits_8 = 8, - kbits_16 = 16, - kbits_32 = 32, - kbits_64 = 64, - kbits_128 = 128, - kbits_256 = 256, - kbits_512 = 512, - kbits_1024 = 1024, - kbits_2048 = 2048 -}; - -//EEPROM addressing error, returned by write() or read() if upper address bound is exceeded -const uint8_t EEPROM_ADDR_ERR = 9; - -/** extEEPROM class */ -class extEEPROM -{ -private: - // the private attribute used to comunicate with the correct I2C SERCOM - TwoWire *communication; - -public: - /** - * I2C clock frequencies - */ - enum twiClockFreq_t { - twiClock100kHz = 100000, //!< twiClock100kHz - twiClock400kHz = 400000 //!< twiClock400kHz - }; - /** - * @brief Constructor - * @param deviceCapacity - * @param nDevice - * @param pageSize - * @param eepromAddr - */ - extEEPROM(eeprom_size_t deviceCapacity, byte nDevice, unsigned int pageSize, - byte eepromAddr = 0x50); - - // It is ready for every I2C Sercom, by default use the main Wire - byte begin(twiClockFreq_t twiFreq = twiClock100kHz, TwoWire *_comm=&Wire); //!< begin() - byte write(unsigned long addr, byte *values, unsigned int nBytes); //!< write() - byte write(unsigned long addr, byte value); //!< write() - byte read(unsigned long addr, byte *values, unsigned int nBytes); //!< read() - int read(unsigned long addr); //!< read() - byte update(unsigned long addr, byte *values, unsigned int nBytes); //!< update() - byte update(unsigned long addr, byte value); //!< update() - unsigned long length(); //!< length() - -private: - uint8_t _eepromAddr; //eeprom i2c address - uint16_t _dvcCapacity; //capacity of one EEPROM device, in kbits - uint8_t _nDevice; //number of devices on the bus - uint16_t _pageSize; //page size in bytes - uint8_t _csShift; //number of bits to shift address for chip select bits in control byte - uint16_t _nAddrBytes; //number of address bytes (1 or 2) - unsigned long _totalCapacity; //capacity of all EEPROM devices on the bus, in bytes -}; - -#endif diff --git a/lib/MySensors/drivers/extEEPROM/keywords.txt b/lib/MySensors/drivers/extEEPROM/keywords.txt deleted file mode 100644 index a9cbe401..00000000 --- a/lib/MySensors/drivers/extEEPROM/keywords.txt +++ /dev/null @@ -1,6 +0,0 @@ -extEEPROM KEYWORD1 -begin KEYWORD2 -write KEYWORD2 -read KEYWORD2 -update KEYWORD2 -length KEYWORD2 diff --git a/lib/MySensors/examples/AirQualitySensor/AirQualitySensor.ino b/lib/MySensors/examples/AirQualitySensor/AirQualitySensor.ino deleted file mode 100644 index f3265d9f..00000000 --- a/lib/MySensors/examples/AirQualitySensor/AirQualitySensor.ino +++ /dev/null @@ -1,219 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * Connect the MQ2 sensor as follows : - * - * A H A >>> 5V - * B >>> A0 - * H >>> GND - * B >>> 10K ohm >>> GND - * - * Contribution: epierre - * Based on http://sandboxelectronics.com/?p=165 - * License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) - * Modified by HEK to work in 1.4 - * - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define CHILD_ID_MQ 0 -/************************Hardware Related Macros************************************/ -#define MQ_SENSOR_ANALOG_PIN (0) //define which analog input channel you are going to use -#define RL_VALUE (5) //define the load resistance on the board, in kilo ohms -#define RO_CLEAN_AIR_FACTOR (9.83) //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO, -//which is derived from the chart in datasheet -/***********************Software Related Macros************************************/ -#define CALIBARAION_SAMPLE_TIMES (50) //define how many samples you are going to take in the calibration phase -#define CALIBRATION_SAMPLE_INTERVAL (500) //define the time interval(in milliseconds) between each samples in the -//calibration phase -#define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation -#define READ_SAMPLE_TIMES (5) //define the time interval(in milliseconds) between each samples in -//normal operation -/**********************Application Related Macros**********************************/ -#define GAS_LPG (0) -#define GAS_CO (1) -#define GAS_SMOKE (2) -/*****************************Globals***********************************************/ -uint32_t SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) -//VARIABLES -float Ro = 10000.0; // this has to be tuned 10K Ohm -int val = 0; // variable to store the value coming from the sensor -uint16_t lastMQ = 0; -float LPGCurve[3] = {2.3,0.21,-0.47}; //two points are taken from the curve. -//with these two points, a line is formed which is "approximately equivalent" -//to the original curve. -//data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59) -float COCurve[3] = {2.3,0.72,-0.34}; //two points are taken from the curve. -//with these two points, a line is formed which is "approximately equivalent" -//to the original curve. -//data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000, 0.15) -float SmokeCurve[3] = {2.3,0.53,-0.44}; //two points are taken from the curve. -//with these two points, a line is formed which is "approximately equivalent" -//to the original curve. -//data format:{ x, y, slope}; point1: (lg200, 0.53), point2:(lg10000,-0.22) - - -MyMessage msg(CHILD_ID_MQ, V_LEVEL); - -void setup() -{ - Ro = MQCalibration( - MQ_SENSOR_ANALOG_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Air Quality Sensor", "1.0"); - - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_MQ, S_AIR_QUALITY); -} - -void loop() -{ - uint16_t valMQ = MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO); - Serial.println(val); - - Serial.print("LPG:"); - Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_LPG) ); - Serial.print( "ppm" ); - Serial.print(" "); - Serial.print("CO:"); - Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO) ); - Serial.print( "ppm" ); - Serial.print(" "); - Serial.print("SMOKE:"); - Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_SMOKE) ); - Serial.print( "ppm" ); - Serial.print("\n"); - - if (valMQ != lastMQ) { - send(msg.set((int16_t)ceil(valMQ))); - lastMQ = ceil(valMQ); - } - - sleep(SLEEP_TIME); //sleep for: sleepTime -} - -/****************** MQResistanceCalculation **************************************** -Input: raw_adc - raw value read from adc, which represents the voltage -Output: the calculated sensor resistance -Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage - across the load resistor and its resistance, the resistance of the sensor - could be derived. -************************************************************************************/ -float MQResistanceCalculation(int raw_adc) -{ - return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc)); -} - -/***************************** MQCalibration **************************************** -Input: mq_pin - analog channel -Output: Ro of the sensor -Remarks: This function assumes that the sensor is in clean air. It use - MQResistanceCalculation to calculates the sensor resistance in clean air - and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about - 10, which differs slightly between different sensors. -************************************************************************************/ -float MQCalibration(int mq_pin) -{ - int i; - float inVal=0; - - for (i=0; i - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * This is an example that demonstrates how to report the battery level for a sensor - * Instructions for measuring battery capacity on A0 are available here: - * http://www.mysensors.org/build/battery - * - */ - - - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point - -uint32_t SLEEP_TIME = 900000; // sleep time between reads (seconds * 1000 milliseconds) -int oldBatteryPcnt = 0; - -void setup() -{ - // use the 1.1 V internal reference -#if defined(__AVR_ATmega2560__) - analogReference(INTERNAL1V1); -#else - analogReference(INTERNAL); -#endif -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Battery Meter", "1.0"); -} - -void loop() -{ - // get the battery Voltage - int sensorValue = analogRead(BATTERY_SENSE_PIN); -#ifdef MY_DEBUG - Serial.println(sensorValue); -#endif - - // 1M, 470K divider across battery and using internal ADC ref of 1.1V - // Sense point is bypassed with 0.1 uF cap to reduce noise at that point - // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts - // 3.44/1023 = Volts per bit = 0.003363075 - - int batteryPcnt = sensorValue / 10; - -#ifdef MY_DEBUG - float batteryV = sensorValue * 0.003363075; - Serial.print("Battery Voltage: "); - Serial.print(batteryV); - Serial.println(" V"); - - Serial.print("Battery percent: "); - Serial.print(batteryPcnt); - Serial.println(" %"); -#endif - - if (oldBatteryPcnt != batteryPcnt) { - // Power up radio after sleep - sendBatteryLevel(batteryPcnt); - oldBatteryPcnt = batteryPcnt; - } - sleep(SLEEP_TIME); -} diff --git a/lib/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino b/lib/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino deleted file mode 100644 index 5b073384..00000000 --- a/lib/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * Interrupt driven binary switch example with dual interrupts - * Author: Patrick 'Anticimex' Fallberg - * Connect one button or door/window reed switch between - * digital I/O pin 3 (BUTTON_PIN below) and GND and the other - * one in similar fashion on digital I/O pin 2. - * This example is designed to fit Arduino Nano/Pro Mini - * - */ - - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define SKETCH_NAME "Binary Sensor" -#define SKETCH_MAJOR_VER "1" -#define SKETCH_MINOR_VER "0" - -#define PRIMARY_CHILD_ID 3 -#define SECONDARY_CHILD_ID 4 - -#define PRIMARY_BUTTON_PIN 2 // Arduino Digital I/O pin for button/reed switch -#define SECONDARY_BUTTON_PIN 3 // Arduino Digital I/O pin for button/reed switch - -#if (PRIMARY_BUTTON_PIN < 2 || PRIMARY_BUTTON_PIN > 3) -#error PRIMARY_BUTTON_PIN must be either 2 or 3 for interrupts to work -#endif -#if (SECONDARY_BUTTON_PIN < 2 || SECONDARY_BUTTON_PIN > 3) -#error SECONDARY_BUTTON_PIN must be either 2 or 3 for interrupts to work -#endif -#if (PRIMARY_BUTTON_PIN == SECONDARY_BUTTON_PIN) -#error PRIMARY_BUTTON_PIN and BUTTON_PIN2 cannot be the same -#endif -#if (PRIMARY_CHILD_ID == SECONDARY_CHILD_ID) -#error PRIMARY_CHILD_ID and SECONDARY_CHILD_ID cannot be the same -#endif - - -// Change to V_LIGHT if you use S_LIGHT in presentation below -MyMessage msg(PRIMARY_CHILD_ID, V_TRIPPED); -MyMessage msg2(SECONDARY_CHILD_ID, V_TRIPPED); - -void setup() -{ - // Setup the buttons - pinMode(PRIMARY_BUTTON_PIN, INPUT_PULLUP); - pinMode(SECONDARY_BUTTON_PIN, INPUT_PULLUP); -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER); - - // Register binary input sensor to sensor_node (they will be created as child devices) - // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. - // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. - present(PRIMARY_CHILD_ID, S_DOOR); - present(SECONDARY_CHILD_ID, S_DOOR); -} - -// Loop will iterate on changes on the BUTTON_PINs -void loop() -{ - uint8_t value; - static uint8_t sentValue=2; - static uint8_t sentValue2=2; - - // Short delay to allow buttons to properly settle - sleep(5); - - value = digitalRead(PRIMARY_BUTTON_PIN); - - if (value != sentValue) { - // Value has changed from last transmission, send the updated value - send(msg.set(value==HIGH)); - sentValue = value; - } - - value = digitalRead(SECONDARY_BUTTON_PIN); - - if (value != sentValue2) { - // Value has changed from last transmission, send the updated value - send(msg2.set(value==HIGH)); - sentValue2 = value; - } - - // Sleep until something happens with the sensor - sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, 0); -} diff --git a/lib/MySensors/examples/CO2Sensor/CO2Sensor.ino b/lib/MySensors/examples/CO2Sensor/CO2Sensor.ino deleted file mode 100644 index 0299f4f1..00000000 --- a/lib/MySensors/examples/CO2Sensor/CO2Sensor.ino +++ /dev/null @@ -1,107 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * MH-Z14 CO2 sensor - * - * Wiring: - * Pad 1, Pad 5: Vin (Voltage input 4.5V-6V) - * Pad 2, Pad 3, Pad 12: GND - * Pad 6: PWM output ==> pin 6 - * - * From: http://davidegironi.blogspot.fr/2014/01/co2-meter-using-ndir-infrared-mh-z14.html - * MH-Z14 has a PWM output, with a sensitivity range of 0ppm to 2000ppm CO2, an accuracy of ±200ppm. - * The cycle is 1004ms±5%, given the duty cicle Th (pulse high), Tl is 1004-Th, we can convert it to CO2 value using the formula: - * CO2ppm = 2000 * (Th - 2ms) /(Th + Tl - 4ms) - * From: http://airqualityegg.wikispaces.com/Sensor+Tests - * - response time is less than 30 s - * - 3 minute warm up time - * datasheet: http://www.futurlec.com/Datasheet/Sensor/MH-Z14.pdf - * Contributor: epierre - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define CHILD_ID_AIQ 0 -#define AIQ_SENSOR_ANALOG_PIN 6 - -uint32_t SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) - -float valAIQ =0.0; -float lastAIQ =0.0; - -MyMessage msg(CHILD_ID_AIQ, V_LEVEL); -MyMessage msg2(CHILD_ID_AIQ, V_UNIT_PREFIX); - -void setup() -{ - pinMode(AIQ_SENSOR_ANALOG_PIN, INPUT); -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("AIQ Sensor CO2 MH-Z14", "1.0"); - - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_AIQ, S_AIR_QUALITY); - send(msg2.set("ppm")); -} - -void loop() -{ - - //uint32_t duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); - while(digitalRead(AIQ_SENSOR_ANALOG_PIN) == HIGH) { - ; - } - //wait for the pin to go HIGH and measure HIGH time - uint32_t duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); - - //Serial.print(duration/1000); Serial.println(" ms "); - //from datasheet - //CO2 ppm = 2000 * (Th - 2ms) / (Th + Tl - 4ms) - // given Tl + Th = 1004 - // Tl = 1004 - Th - // = 2000 * (Th - 2ms) / (Th + 1004 - Th -4ms) - // = 2000 * (Th - 2ms) / 1000 = 2 * (Th - 2ms) - long co2ppm = 2 * ((duration/1000) - 2); - //Serial.print(co2ppm); - if ((co2ppm != lastAIQ)&&(abs(co2ppm-lastAIQ)>=10)) { - send(msg.set((int32_t)ceil(co2ppm))); - lastAIQ = ceil(co2ppm); - } - - //Serial.println(); - - // Power down the radio. Note that the radio will get powered back up - // on the next write() call. - sleep(SLEEP_TIME); //sleep for: sleepTime -} diff --git a/lib/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino b/lib/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino deleted file mode 100644 index 9ef6186a..00000000 --- a/lib/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * This sketch clears radioId, relayId and other routing information in EEPROM back to factory default - * - */ -// load core modules only -#define MY_CORE_ONLY - -#include - -void setup() -{ - Serial.begin(MY_BAUD_RATE); - Serial.println("Started clearing. Please wait..."); - for (uint16_t i=0; i - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - February 15, 2014 - Bruce Lacey - * Version 1.1 - August 13, 2014 - Converted to 1.4 (hek) - * - * DESCRIPTION - * This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad - * Vera Arduino Sensor project. - * Developed by Bruce Lacey, inspired by Hek's MySensor's example sketches. - * - * The circuit uses a MOSFET for Pulse-Wave-Modulation to dim the attached LED or LED strip. - * The MOSFET Gate pin is connected to Arduino pin 3 (LED_PIN), the MOSFET Drain pin is connected - * to the LED negative terminal and the MOSFET Source pin is connected to ground. - * - * This sketch is extensible to support more than one MOSFET/PWM dimmer per circuit. - * http://www.mysensors.org/build/dimmer - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define SN "DimmableLED" -#define SV "1.1" - -#define LED_PIN 3 // Arduino pin attached to MOSFET Gate pin -#define FADE_DELAY 10 // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim) - -static int16_t currentLevel = 0; // Current dim level... -MyMessage dimmerMsg(0, V_DIMMER); -MyMessage lightMsg(0, V_LIGHT); - - -/*** - * Dimmable LED initialization method - */ -void setup() -{ - // Pull the gateway's current dim level - restore light level upon node power-up - request( 0, V_DIMMER ); -} - -void presentation() -{ - // Register the LED Dimmable Light with the gateway - present( 0, S_DIMMER ); - - sendSketchInfo(SN, SV); -} - -/*** - * Dimmable LED main processing loop - */ -void loop() -{ -} - - - -void receive(const MyMessage &message) -{ - if (message.getType() == V_LIGHT || message.getType() == V_DIMMER) { - - // Retrieve the power or dim level from the incoming request message - int requestedLevel = atoi( message.data ); - - // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on] - requestedLevel *= ( message.getType() == V_LIGHT ? 100 : 1 ); - - // Clip incoming level to valid range of 0 to 100 - requestedLevel = requestedLevel > 100 ? 100 : requestedLevel; - requestedLevel = requestedLevel < 0 ? 0 : requestedLevel; - - Serial.print( "Changing level to " ); - Serial.print( requestedLevel ); - Serial.print( ", from " ); - Serial.println( currentLevel ); - - fadeToLevel( requestedLevel ); - - // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value... - send(lightMsg.set(currentLevel > 0)); - - // hek comment: Is this really nessesary? - send( dimmerMsg.set(currentLevel) ); - - - } -} - -/*** - * This method provides a graceful fade up/down effect - */ -void fadeToLevel( int toLevel ) -{ - - int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1; - - while ( currentLevel != toLevel ) { - currentLevel += delta; - analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) ); - delay( FADE_DELAY ); - } -} diff --git a/lib/MySensors/examples/DimmableLight/DimmableLight.ino b/lib/MySensors/examples/DimmableLight/DimmableLight.ino deleted file mode 100644 index f290cbf2..00000000 --- a/lib/MySensors/examples/DimmableLight/DimmableLight.ino +++ /dev/null @@ -1,158 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - January 30, 2015 - Developed by GizMoCuz (Domoticz) - * - * DESCRIPTION - * This sketch provides an example how to implement a Dimmable Light - * It is pure virtual and it logs messages to the serial output - * It can be used as a base sketch for actual hardware. - * Stores the last light state and level in eeprom. - * - */ - -// Enable debug prints -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define CHILD_ID_LIGHT 1 - -#define EPROM_LIGHT_STATE 1 -#define EPROM_DIMMER_LEVEL 2 - -#define LIGHT_OFF 0 -#define LIGHT_ON 1 - -#define SN "Dimmable Light" -#define SV "1.0" - -int16_t LastLightState=LIGHT_OFF; -int16_t LastDimValue=100; - -MyMessage lightMsg(CHILD_ID_LIGHT, V_LIGHT); -MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER); - -void setup() -{ - //Retreive our last light state from the eprom - int LightState=loadState(EPROM_LIGHT_STATE); - if (LightState<=1) { - LastLightState=LightState; - int DimValue=loadState(EPROM_DIMMER_LEVEL); - if ((DimValue>0)&&(DimValue<=100)) { - //There should be no Dim value of 0, this would mean LIGHT_OFF - LastDimValue=DimValue; - } - } - - //Here you actually switch on/off the light with the last known dim level - SetCurrentState2Hardware(); - - Serial.println( "Node ready to receive messages..." ); -} - -void presentation() -{ - // Send the Sketch Version Information to the Gateway - sendSketchInfo(SN, SV); - - present(CHILD_ID_LIGHT, S_DIMMER ); -} - -void loop() -{ -} - -void receive(const MyMessage &message) -{ - if (message.getType() == V_LIGHT) { - Serial.println( "V_LIGHT command received..." ); - - int lstate= atoi( message.data ); - if ((lstate<0)||(lstate>1)) { - Serial.println( "V_LIGHT data invalid (should be 0/1)" ); - return; - } - LastLightState=lstate; - saveState(EPROM_LIGHT_STATE, LastLightState); - - if ((LastLightState==LIGHT_ON)&&(LastDimValue==0)) { - //In the case that the Light State = On, but the dimmer value is zero, - //then something (probably the controller) did something wrong, - //for the Dim value to 100% - LastDimValue=100; - saveState(EPROM_DIMMER_LEVEL, LastDimValue); - } - - //When receiving a V_LIGHT command we switch the light between OFF and the last received dimmer value - //This means if you previously set the lights dimmer value to 50%, and turn the light ON - //it will do so at 50% - } else if (message.getType() == V_DIMMER) { - Serial.println( "V_DIMMER command received..." ); - int dimvalue= atoi( message.data ); - if ((dimvalue<0)||(dimvalue>100)) { - Serial.println( "V_DIMMER data invalid (should be 0..100)" ); - return; - } - if (dimvalue==0) { - LastLightState=LIGHT_OFF; - } else { - LastLightState=LIGHT_ON; - LastDimValue=dimvalue; - saveState(EPROM_DIMMER_LEVEL, LastDimValue); - } - } else { - Serial.println( "Invalid command received..." ); - return; - } - - //Here you set the actual light state/level - SetCurrentState2Hardware(); -} - -void SetCurrentState2Hardware() -{ - if (LastLightState==LIGHT_OFF) { - Serial.println( "Light state: OFF" ); - } else { - Serial.print( "Light state: ON, Level: " ); - Serial.println( LastDimValue ); - } - - //Send current state to the controller - SendCurrentState2Controller(); -} - -void SendCurrentState2Controller() -{ - if ((LastLightState==LIGHT_OFF)||(LastDimValue==0)) { - send(dimmerMsg.set((int16_t)0)); - } else { - send(dimmerMsg.set(LastDimValue)); - } -} diff --git a/lib/MySensors/examples/DustSensor/DustSensor.ino b/lib/MySensors/examples/DustSensor/DustSensor.ino deleted file mode 100644 index 82a6df97..00000000 --- a/lib/MySensors/examples/DustSensor/DustSensor.ino +++ /dev/null @@ -1,104 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - epierre - * Converted to 1.4 by Henrik Ekblad - * - * DESCRIPTION - * Arduino Dust Sensort - * - * connect the sensor as follows : - * - * VCC >>> 5V - * A >>> A0 - * GND >>> GND - * - * Based on: http://www.dfrobot.com/wiki/index.php/Sharp_GP2Y1010AU - * Authors: Cyrille Médard de Chardon (serialC), Christophe Trefois (Trefex) - * - * http://www.mysensors.org/build/dust - * - */ - -// Enable debug prints -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define CHILD_ID_DUST 0 -#define DUST_SENSOR_ANALOG_PIN 1 - -uint32_t SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) -//VARIABLES -int val = 0; // variable to store the value coming from the sensor -float valDUST =0.0; -float lastDUST =0.0; -int samplingTime = 280; -int deltaTime = 40; -int sleepTime = 9680; -float calcVoltage = 0; -float dustDensity = 0; - -MyMessage dustMsg(CHILD_ID_DUST, V_LEVEL); - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Dust Sensor", "1.1"); - - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_DUST, S_DUST); -} - -void loop() -{ - uint16_t voMeasured = analogRead(DUST_SENSOR_ANALOG_PIN);// Get DUST value - - // 0 - 5V mapped to 0 - 1023 integer values - // recover voltage - calcVoltage = voMeasured * (5.0 / 1024.0); - - // linear equation taken from http://www.howmuchsnow.com/arduino/airquality/ - // Chris Nafis (c) 2012 - dustDensity = (0.17 * calcVoltage - 0.1)*1000; - - Serial.print("Raw Signal Value (0-1023): "); - Serial.print(voMeasured); - - Serial.print(" - Voltage: "); - Serial.print(calcVoltage); - - Serial.print(" - Dust Density: "); - Serial.println(dustDensity); // unit: ug/m3 - - if (ceil(dustDensity) != lastDUST) { - send(dustMsg.set((int16_t)ceil(dustDensity))); - lastDUST = ceil(dustDensity); - } - - sleep(SLEEP_TIME); -} diff --git a/lib/MySensors/examples/DustSensorDSM/DustSensorDSM.ino b/lib/MySensors/examples/DustSensorDSM/DustSensorDSM.ino deleted file mode 100644 index 39dd8b3d..00000000 --- a/lib/MySensors/examples/DustSensorDSM/DustSensorDSM.ino +++ /dev/null @@ -1,151 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * Dust Sensor for SamYoung DSM501 - * connect the sensor as follows : - * Pin 2 of dust sensor PM1 -> Digital 3 (PMW) - * Pin 3 of dust sensor -> +5V - * Pin 4 of dust sensor PM2.5 -> Digital 6 (PWM) - * Pin 5 of dust sensor -> Ground - * Datasheet: http://www.samyoungsnc.com/products/3-1%20Specification%20DSM501.pdf -* Contributor: epierre -**/ - -// Enable debug prints -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define CHILD_ID_DUST_PM10 0 -#define CHILD_ID_DUST_PM25 1 -#define DUST_SENSOR_DIGITAL_PIN_PM10 6 -#define DUST_SENSOR_DIGITAL_PIN_PM25 3 - -uint32_t SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) -//VARIABLES -int val = 0; // variable to store the value coming from the sensor -float valDUSTPM25 =0.0; -float lastDUSTPM25 =0.0; -float valDUSTPM10 =0.0; -float lastDUSTPM10 =0.0; -uint32_t duration; -uint32_t starttime; -uint32_t endtime; -uint32_t sampletime_ms = 30000; -uint32_t lowpulseoccupancy = 0; -float ratio = 0; -long concentrationPM25 = 0; -long concentrationPM10 = 0; - -MyMessage dustMsgPM10(CHILD_ID_DUST_PM10, V_LEVEL); -MyMessage msgPM10(CHILD_ID_DUST_PM10, V_UNIT_PREFIX); -MyMessage dustMsgPM25(CHILD_ID_DUST_PM25, V_LEVEL); -MyMessage msgPM25(CHILD_ID_DUST_PM25, V_UNIT_PREFIX); - -void setup() -{ - pinMode(DUST_SENSOR_DIGITAL_PIN_PM10,INPUT); - pinMode(DUST_SENSOR_DIGITAL_PIN_PM25,INPUT); -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Dust Sensor DSM501", "1.4"); - - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_DUST_PM10, S_DUST); - send(msgPM10.set("ppm")); - present(CHILD_ID_DUST_PM25, S_DUST); - send(msgPM25.set("ppm")); -} - -void loop() -{ - - //get PM 2.5 density of particles over 2.5 µm. - concentrationPM25=(long)getPM(DUST_SENSOR_DIGITAL_PIN_PM25); - Serial.print("PM25: "); - Serial.println(concentrationPM25); - Serial.print("\n"); - - if ((concentrationPM25 != lastDUSTPM25)&&(concentrationPM25>0)) { - send(dustMsgPM25.set((int32_t)ceil(concentrationPM25))); - lastDUSTPM25 = ceil(concentrationPM25); - } - - //get PM 1.0 - density of particles over 1 µm. - concentrationPM10=getPM(DUST_SENSOR_DIGITAL_PIN_PM10); - Serial.print("PM10: "); - Serial.println(concentrationPM10); - Serial.print("\n"); - //ppmv=mg/m3 * (0.08205*Tmp)/Molecular_mass - //0.08205 = Universal gas constant in atm·m3/(kmol·K) - int temp=20; //external temperature, if you can replace this with a DHT11 or better - long ppmv=(concentrationPM10*0.0283168/100/1000) * (0.08205*temp)/0.01; - - if ((ceil(concentrationPM10) != lastDUSTPM10)&&((long)concentrationPM10>0)) { - send(dustMsgPM10.set((int32_t)ppmv)); - lastDUSTPM10 = ceil(concentrationPM10); - } - - //sleep to save on radio - sleep(SLEEP_TIME); - -} - - -long getPM(int DUST_SENSOR_DIGITAL_PIN) -{ - - starttime = millis(); - - while (1) { - - duration = pulseIn(DUST_SENSOR_DIGITAL_PIN, LOW); - lowpulseoccupancy += duration; - endtime = millis(); - - if ((endtime-starttime) > sampletime_ms) { - ratio = (lowpulseoccupancy-endtime+starttime)/(sampletime_ms*10.0); // Integer percentage 0=>100 - long concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve - //Serial.print("lowpulseoccupancy:"); - //Serial.print(lowpulseoccupancy); - //Serial.print("\n"); - //Serial.print("ratio:"); - //Serial.print(ratio); - //Serial.print("\n"); - //Serial.print("DSM501A:"); - //Serial.println(concentration); - //Serial.print("\n"); - - lowpulseoccupancy = 0; - return(concentration); - } - } -} diff --git a/lib/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino b/lib/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino deleted file mode 100644 index 91f3f53c..00000000 --- a/lib/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino +++ /dev/null @@ -1,169 +0,0 @@ -/* - The MySensors Arduino library handles the wireless radio link and protocol - between your home built sensors/actuators and HA controller of choice. - The sensors forms a self healing radio network with optional repeaters. Each - repeater and gateway builds a routing tables in EEPROM which keeps track of the - network topology allowing messages to be routed to nodes. - - Created by Henrik Ekblad - Copyright (C) 2013-2019 Sensnology AB - Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - - Documentation: http://www.mysensors.org - Support Forum: http://forum.mysensors.org - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as published by the Free Software Foundation. - - ******************************* - - REVISION HISTORY - Version 1.0 - Henrik Ekblad - Version 1.1 - Peter Andersson added millis watt calculation if time between pulses > 1h - - DESCRIPTION - This sketch provides an example how to implement a LM393 PCB - Use this sensor to measure kWh and Watt of your house meter - You need to set the correct pulsefactor of your meter (blinks per kWh). - The sensor starts by fetching current kWh value from gateway. - Reports both kWh and Watt back to gateway. - - Unfortunately millis() won't increment when the Arduino is in - sleepmode. So we cannot make this sensor sleep if we also want - to calculate/report watt value. - http://www.mysensors.org/build/pulse_power -*/ - -// Enable debug prints -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) -#define PULSE_FACTOR 1000 // Number of blinks per kWh of your meter. Normally 1000. -#define SLEEP_MODE false // Watt value can only be reported when sleep mode is false. -#define MAX_WATT 10000 // Max watt value to report. This filters outliers. -#define CHILD_ID 1 // Id of the sensor child - -uint32_t SEND_FREQUENCY = - 20000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. -double ppwh = ((double)PULSE_FACTOR) / 1000; // Pulses per watt hour -bool pcReceived = false; -volatile uint32_t pulseCount = 0; -volatile uint32_t lastBlinkmicros = 0; -volatile uint32_t lastBlinkmillis = 0; -volatile uint32_t watt = 0; -uint32_t oldPulseCount = 0; -uint32_t oldWatt = 0; -double oldkWh; -uint32_t lastSend; -MyMessage wattMsg(CHILD_ID, V_WATT); -MyMessage kWhMsg(CHILD_ID, V_KWH); -MyMessage pcMsg(CHILD_ID, V_VAR1); - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#define IRQ_HANDLER_ATTR ICACHE_RAM_ATTR -#else -#define IRQ_HANDLER_ATTR -#endif - -void IRQ_HANDLER_ATTR onPulse() -{ - if (!SLEEP_MODE) { - uint32_t newBlinkmicros = micros(); - uint32_t newBlinkmillis = millis(); - uint32_t intervalmicros = newBlinkmicros - lastBlinkmicros; - uint32_t intervalmillis = newBlinkmillis - lastBlinkmillis; - if (intervalmicros < 10000L && intervalmillis < 10L) { // Sometimes we get interrupt on RISING - return; - } - if (intervalmillis < 360000) { // Less than an hour since last pulse, use microseconds - watt = (3600000000.0 / intervalmicros) / ppwh; - } else { - watt = (3600000.0 / intervalmillis) / - ppwh; // more thAn an hour since last pulse, use milliseconds as micros will overflow after 70min - } - lastBlinkmicros = newBlinkmicros; - lastBlinkmillis = newBlinkmillis; - } - pulseCount++; -} - -void setup() -{ - // Fetch last known pulse count value from gw - request(CHILD_ID, V_VAR1); - - // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output - // If no pullup is used, the reported usage will be too high because of the floating pin - pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP); - - attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, RISING); - lastSend = millis(); -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo(F("Energy Meter"), F("1.1")); - - // Register this device as power sensor - present(CHILD_ID, S_POWER); -} - -void loop() -{ - uint32_t now = millis(); - // Only send values at a maximum frequency or woken up from sleep - bool sendTime = now - lastSend > SEND_FREQUENCY; - if (pcReceived && (SLEEP_MODE || sendTime)) { - // New watt value has been calculated - if (!SLEEP_MODE && watt != oldWatt) { - // Check that we don't get unreasonable large watt value, which - // could happen when long wraps or false interrupt triggered - if (watt < ((uint32_t)MAX_WATT)) { - send(wattMsg.set(watt)); // Send watt value to gw - } - Serial.print("Watt:"); - Serial.println(watt); - oldWatt = watt; - } - - // Pulse count value has changed - if (pulseCount != oldPulseCount) { - send(pcMsg.set(pulseCount)); // Send pulse count value to gw - double kWh = ((double)pulseCount / ((double)PULSE_FACTOR)); - oldPulseCount = pulseCount; - if (kWh != oldkWh) { - send(kWhMsg.set(kWh, 4)); // Send kWh value to gw - oldkWh = kWh; - } - } - lastSend = now; - } else if (sendTime && !pcReceived) { - // No pulse count value received from controller. Try requesting it again. - request(CHILD_ID, V_VAR1); - lastSend = now; - } - - if (SLEEP_MODE) { - sleep(SEND_FREQUENCY, false); - } -} - -void receive(const MyMessage &message) -{ - if (message.getType()==V_VAR1) { - pulseCount = oldPulseCount = message.getLong(); - Serial.print("Received last pulse count value from gw:"); - Serial.println(pulseCount); - pcReceived = true; - } -} diff --git a/lib/MySensors/examples/GatewayESP32/GatewayESP32.ino b/lib/MySensors/examples/GatewayESP32/GatewayESP32.ino deleted file mode 100644 index 3fa69521..00000000 --- a/lib/MySensors/examples/GatewayESP32/GatewayESP32.ino +++ /dev/null @@ -1,84 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - tekka - * - * DESCRIPTION - * The ESP32 gateway sends data received from sensors to the WiFi link. - * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. - * - * Make sure to fill in your ssid and WiFi password below. - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enables and select radio type (if attached) -#define MY_RADIO_RF24 -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_GATEWAY_ESP32 - -#define MY_WIFI_SSID "MySSID" -#define MY_WIFI_PASSWORD "MyVerySecretPassword" - -// Enable UDP communication -//#define MY_USE_UDP // If using UDP you need to set MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS below - -// Set the hostname for the WiFi Client. This is the hostname -// passed to the DHCP server if not static. -#define MY_HOSTNAME "ESP32_GW" - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -//#define MY_IP_ADDRESS 192,168,1,100 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,1,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// The port to keep open on node server mode -#define MY_PORT 5003 - -// How many clients should be able to connect to this gateway (default 1) -#define MY_GATEWAY_MAX_CLIENTS 2 - -// Controller ip address. Enables client mode (default is "server" mode). -// Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere. -//#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 68 -//#define MY_CONTROLLER_URL_ADDRESS "my.controller.org" - -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attached sensors data here -} diff --git a/lib/MySensors/examples/GatewayESP32MQTTClient/GatewayESP32MQTTClient.ino b/lib/MySensors/examples/GatewayESP32MQTTClient/GatewayESP32MQTTClient.ino deleted file mode 100644 index 0aa1f8d9..00000000 --- a/lib/MySensors/examples/GatewayESP32MQTTClient/GatewayESP32MQTTClient.ino +++ /dev/null @@ -1,90 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - tekka - * - * DESCRIPTION - * The ESP32 gateway sends data received from sensors to the WiFi link. - * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. - * - * Make sure to fill in your ssid and WiFi password below. - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enables and select radio type (if attached) -#define MY_RADIO_RF24 -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_GATEWAY_MQTT_CLIENT -#define MY_GATEWAY_ESP32 - -// Set this node's subscribe and publish topic prefix -#define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out" -#define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in" - -// Set MQTT client id -#define MY_MQTT_CLIENT_ID "mysensors-1" - -// Enable these if your MQTT broker requires usenrame/password -//#define MY_MQTT_USER "username" -//#define MY_MQTT_PASSWORD "password" - -// Set WIFI SSID and password -#define MY_WIFI_SSID "MySSID" -#define MY_WIFI_PASSWORD "MyVerySecretPassword" - -// Set the hostname for the WiFi Client. This is the hostname -// passed to the DHCP server if not static. -#define MY_HOSTNAME "ESP32_MQTT_GW" - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -//#define MY_IP_ADDRESS 192,168,178,87 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,178,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// MQTT broker ip address. -#define MY_CONTROLLER_IP_ADDRESS 192, 168, 1, 5 - -// The MQTT broker port to to open -#define MY_PORT 1883 - -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attech sensors data here -} - diff --git a/lib/MySensors/examples/GatewayESP32OTA/GatewayESP32OTA.ino b/lib/MySensors/examples/GatewayESP32OTA/GatewayESP32OTA.ino deleted file mode 100644 index 2610baba..00000000 --- a/lib/MySensors/examples/GatewayESP32OTA/GatewayESP32OTA.ino +++ /dev/null @@ -1,120 +0,0 @@ -/** - The MySensors Arduino library handles the wireless radio link and protocol - between your home built sensors/actuators and HA controller of choice. - The sensors forms a self healing radio network with optional repeaters. Each - repeater and gateway builds a routing tables in EEPROM which keeps track of the - network topology allowing messages to be routed to nodes. - - Created by Henrik Ekblad - Copyright (C) 2013-2019 Sensnology AB - Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - - Documentation: http://www.mysensors.org - Support Forum: http://forum.mysensors.org - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as published by the Free Software Foundation. - - ******************************* - - REVISION HISTORY - Version 1.0 - tekka - Contribution by Berk - - DESCRIPTION - The ESP32 gateway sends data received from sensors to the WiFi link. - The gateway also accepts input on ethernet interface, which is then sent out to the radio network. - - Make sure to fill in your ssid and WiFi password below. -*/ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enables and select radio type (if attached) -#define MY_RADIO_RF24 -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_GATEWAY_ESP32 - -#define MY_WIFI_SSID "MySSID" -#define MY_WIFI_PASSWORD "MyVerySecretPassword" - -// Set the hostname for the WiFi Client. This is the hostname -// passed to the DHCP server if not static. -#define MY_HOSTNAME "ESP32_GW" - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -//#define MY_IP_ADDRESS 192,168,1,100 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,1,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// The port to keep open on node server mode -#define MY_PORT 5003 - -// How many clients should be able to connect to this gateway (default 1) -#define MY_GATEWAY_MAX_CLIENTS 2// Set blinking period - - -// Advanced Gateway Options -//#define MY_DEFAULT_LED_BLINK_PERIOD 50 - -// Flash leds on rx/tx/err -// Led pins used if blinking feature is enabled above -//#define MY_DEFAULT_ERR_LED_PIN 32 // Transfer data error led pin -//#define MY_DEFAULT_RX_LED_PIN 25 // Receive Data led pin -//#define MY_DEFAULT_TX_LED_PIN 27 // Transmit Data led pin - -//#define MY_WITH_LEDS_BLINKING_INVERSE // At the time of Error, Receive, Transmit the pin is at a high level - -#include -#include - -void setup() -{ - // Setup locally attached sensors - ArduinoOTA.onStart([]() { - Serial.println("Start updating"); - }); - ArduinoOTA.onEnd([]() { - Serial.println("\nEnd updating"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100))); - }); - ArduinoOTA.onError([](ota_error_t error) { - Serial.printf("Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) { - Serial.println("Auth Failed"); - } else if (error == OTA_BEGIN_ERROR) { - Serial.println("Begin Failed"); - } else if (error == OTA_CONNECT_ERROR) { - Serial.println("Connect Failed"); - } else if (error == OTA_RECEIVE_ERROR) { - Serial.println("Receive Failed"); - } else if (error == OTA_END_ERROR) { - Serial.println("End Failed"); - } - }); - ArduinoOTA.begin(); - - - - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attached sensors data here - - ArduinoOTA.handle(); -} \ No newline at end of file diff --git a/lib/MySensors/examples/GatewayESP8266/GatewayESP8266.ino b/lib/MySensors/examples/GatewayESP8266/GatewayESP8266.ino deleted file mode 100644 index 9326400c..00000000 --- a/lib/MySensors/examples/GatewayESP8266/GatewayESP8266.ino +++ /dev/null @@ -1,130 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * Contribution by a-lurker and Anticimex, - * Contribution by Norbert Truchsess - * Contribution by Ivo Pullens (ESP8266 support) - * - * DESCRIPTION - * The EthernetGateway sends data received from sensors to the WiFi link. - * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. - * - * VERA CONFIGURATION: - * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin. - * E.g. If you want to use the default values in this sketch enter: 192.168.178.66:5003 - * - * LED purposes: - * - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs in your sketch, only the LEDs that is defined is used. - * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received - * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly - * - ERR (red) - fast blink on error during transmission error or receive crc error - * - * See https://www.mysensors.org/build/connect_radio for wiring instructions. - * - * If you are using a "barebone" ESP8266, see - * https://www.mysensors.org/build/esp8266_gateway#wiring-for-barebone-esp8266 - * - * Inclusion mode button: - * - Connect GPIO5 (=D1) via switch to GND ('inclusion switch') - * - * Hardware SHA204 signing is currently not supported! - * - * Make sure to fill in your ssid and WiFi password below for ssid & pass. - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Use a bit lower baudrate for serial prints on ESP8266 than default in MyConfig.h -#define MY_BAUD_RATE 9600 - -// Enables and select radio type (if attached) -#define MY_RADIO_RF24 -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_GATEWAY_ESP8266 - -#define MY_WIFI_SSID "MySSID" -#define MY_WIFI_PASSWORD "MyVerySecretPassword" - -// Enable UDP communication -//#define MY_USE_UDP // If using UDP you need to set MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS below - -// Set the hostname for the WiFi Client. This is the hostname -// it will pass to the DHCP server if not static. -#define MY_HOSTNAME "ESP8266_GW" - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -//#define MY_IP_ADDRESS 192,168,178,87 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,178,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// The port to keep open on node server mode -#define MY_PORT 5003 - -// How many clients should be able to connect to this gateway (default 1) -#define MY_GATEWAY_MAX_CLIENTS 2 - -// Controller ip address. Enables client mode (default is "server" mode). -// Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere. -//#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 68 -//#define MY_CONTROLLER_URL_ADDRESS "my.controller.org" - -// Enable inclusion mode -//#define MY_INCLUSION_MODE_FEATURE - -// Enable Inclusion mode button on gateway -//#define MY_INCLUSION_BUTTON_FEATURE -// Set inclusion mode duration (in seconds) -//#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -//#define MY_INCLUSION_MODE_BUTTON_PIN D1 - -// Set blinking period -//#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Flash leds on rx/tx/err -// Led pins used if blinking feature is enabled above -//#define MY_DEFAULT_ERR_LED_PIN 16 // Error led pin -//#define MY_DEFAULT_RX_LED_PIN 16 // Receive led pin -//#define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED - -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attached sensors data here -} - diff --git a/lib/MySensors/examples/GatewayESP8266MQTTClient/GatewayESP8266MQTTClient.ino b/lib/MySensors/examples/GatewayESP8266MQTTClient/GatewayESP8266MQTTClient.ino deleted file mode 100644 index b8051d55..00000000 --- a/lib/MySensors/examples/GatewayESP8266MQTTClient/GatewayESP8266MQTTClient.ino +++ /dev/null @@ -1,129 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * - * DESCRIPTION - * The ESP8266 MQTT gateway sends radio network (or locally attached sensors) data to your MQTT broker. - * The node also listens to MY_MQTT_TOPIC_PREFIX and sends out those messages to the radio network - * - * LED purposes: - * - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs in your sketch - * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received - * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly - * - ERR (red) - fast blink on error during transmission error or receive crc error - * - * See https://www.mysensors.org/build/connect_radio for wiring instructions. - * - * If you are using a "barebone" ESP8266, see - * https://www.mysensors.org/build/esp8266_gateway#wiring-for-barebone-esp8266 - * - * Inclusion mode button: - * - Connect GPIO5 (=D1) via switch to GND ('inclusion switch') - * - * Hardware SHA204 signing is currently not supported! - * - * Make sure to fill in your ssid and WiFi password below for ssid & pass. - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Use a bit lower baudrate for serial prints on ESP8266 than default in MyConfig.h -#define MY_BAUD_RATE 9600 - -// Enables and select radio type (if attached) -#define MY_RADIO_RF24 -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_GATEWAY_MQTT_CLIENT -#define MY_GATEWAY_ESP8266 - -// Set this node's subscribe and publish topic prefix -#define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out" -#define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in" - -// Set MQTT client id -#define MY_MQTT_CLIENT_ID "mysensors-1" - -// Enable these if your MQTT broker requires username/password -//#define MY_MQTT_USER "username" -//#define MY_MQTT_PASSWORD "password" - -// Set WIFI SSID and password -#define MY_WIFI_SSID "MySSID" -#define MY_WIFI_PASSWORD "MyVerySecretPassword" - -// Set the hostname for the WiFi Client. This is the hostname -// passed to the DHCP server if not static. -#define MY_HOSTNAME "ESP8266_MQTT_GW" - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -//#define MY_IP_ADDRESS 192,168,178,87 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,178,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// MQTT broker ip address. -#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 68 - -//MQTT broker if using URL instead of ip address. -// #define MY_CONTROLLER_URL_ADDRESS "test.mosquitto.org" - -// The MQTT broker port to to open -#define MY_PORT 1883 - -// Enable inclusion mode -//#define MY_INCLUSION_MODE_FEATURE -// Enable Inclusion mode button on gateway -//#define MY_INCLUSION_BUTTON_FEATURE -// Set inclusion mode duration (in seconds) -//#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -//#define MY_INCLUSION_MODE_BUTTON_PIN D1 - -// Set blinking period -//#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Flash leds on rx/tx/err -//#define MY_DEFAULT_ERR_LED_PIN 16 // Error led pin -//#define MY_DEFAULT_RX_LED_PIN 16 // Receive led pin -//#define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED - -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attached sensors data here -} - diff --git a/lib/MySensors/examples/GatewayESP8266OTA/GatewayESP8266OTA.ino b/lib/MySensors/examples/GatewayESP8266OTA/GatewayESP8266OTA.ino deleted file mode 100644 index 56fa4a4a..00000000 --- a/lib/MySensors/examples/GatewayESP8266OTA/GatewayESP8266OTA.ino +++ /dev/null @@ -1,156 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * Contribution by tekka, - * Contribution by a-lurker and Anticimex, - * Contribution by Norbert Truchsess - * Contribution by Ivo Pullens (ESP8266 support) - * - * DESCRIPTION - * The EthernetGateway sends data received from sensors to the WiFi link. - * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. - * - * VERA CONFIGURATION: - * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin. - * E.g. If you want to use the default values in this sketch enter: 192.168.178.66:5003 - * - * LED purposes: - * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h - * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received - * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly - * - ERR (red) - fast blink on error during transmission error or receive crc error - * - * See https://www.mysensors.org/build/connect_radio for wiring instructions. - * - * If you are using a "barebone" ESP8266, see - * https://www.mysensors.org/build/esp8266_gateway#wiring-for-barebone-esp8266 - * - * Inclusion mode button: - * - Connect GPIO5 via switch to GND ('inclusion switch') - * - * Hardware SHA204 signing is currently not supported! - * - * Make sure to fill in your ssid and WiFi password below for ssid & pass. - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Use a bit lower baudrate for serial prints on ESP8266 than default in MyConfig.h -#define MY_BAUD_RATE 9600 - -// Enables and select radio type (if attached) -#define MY_RADIO_RF24 -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_GATEWAY_ESP8266 - -#define MY_WIFI_SSID "MySSID" -#define MY_WIFI_PASSWORD "MyVerySecretPassword" - -// Set the hostname for the WiFi Client. This is the hostname -// passed to the DHCP server if not static. -#define MY_HOSTNAME "ESP8266_GW" - -// Enable UDP communication -//#define MY_USE_UDP // If using UDP you need to set MY_CONTROLLER_IP_ADDRESS below - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -//#define MY_IP_ADDRESS 192,168,178,87 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,178,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// The port to keep open on node server mode -#define MY_PORT 5003 - -// How many clients should be able to connect to this gateway (default 1) -#define MY_GATEWAY_MAX_CLIENTS 2 - -// Controller ip address. Enables client mode (default is "server" mode). -// Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere. -//#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 68 - -// Enable inclusion mode -#define MY_INCLUSION_MODE_FEATURE - -// Enable Inclusion mode button on gateway -//#define MY_INCLUSION_BUTTON_FEATURE -// Set inclusion mode duration (in seconds) -#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -#define MY_INCLUSION_MODE_BUTTON_PIN 3 - -// Set blinking period -// #define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Flash leds on rx/tx/err -// Led pins used if blinking feature is enabled above -#define MY_DEFAULT_ERR_LED_PIN 16 // Error led pin -#define MY_DEFAULT_RX_LED_PIN 16 // Receive led pin -#define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED - -#include -#include - -void setup() -{ - // Setup locally attached sensors - ArduinoOTA.onStart([]() { - Serial.println("ArduinoOTA start"); - }); - ArduinoOTA.onEnd([]() { - Serial.println("\nArduinoOTA end"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100))); - }); - ArduinoOTA.onError([](ota_error_t error) { - Serial.printf("Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) { - Serial.println("Auth Failed"); - } else if (error == OTA_BEGIN_ERROR) { - Serial.println("Begin Failed"); - } else if (error == OTA_CONNECT_ERROR) { - Serial.println("Connect Failed"); - } else if (error == OTA_RECEIVE_ERROR) { - Serial.println("Receive Failed"); - } else if (error == OTA_END_ERROR) { - Serial.println("End Failed"); - } - }); - ArduinoOTA.begin(); -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attached sensors data here - ArduinoOTA.handle(); -} - diff --git a/lib/MySensors/examples/GatewayGSMMQTTClient/GatewayGSMMQTTClient.ino b/lib/MySensors/examples/GatewayGSMMQTTClient/GatewayGSMMQTTClient.ino deleted file mode 100644 index 37d62611..00000000 --- a/lib/MySensors/examples/GatewayGSMMQTTClient/GatewayGSMMQTTClient.ino +++ /dev/null @@ -1,137 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Rait Lotamõis - * - * DESCRIPTION - * The TinyGSM MQTT gateway sends radio network (or locally attached sensors) data to your MQTT broker using a GSM modem or optionally an ESP8266 as a WiFi modem. - * The node also listens to MY_MQTT_TOPIC_PREFIX and sends out those messages to the radio network - * - * LED purposes: - * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h - * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved - * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly - * - ERR (red) - fast blink on error during transmission error or recieve crc error - */ - - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enables and select radio type (if attached) -#define MY_RADIO_RF24 -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_GATEWAY_MQTT_CLIENT - -// Enable GSM modem support -#define MY_GATEWAY_TINYGSM - -// Define your modem -#define TINY_GSM_MODEM_SIM800 -// #define TINY_GSM_MODEM_SIM808 -// #define TINY_GSM_MODEM_SIM900 -// #define TINY_GSM_MODEM_A6 -// #define TINY_GSM_MODEM_A7 -// #define TINY_GSM_MODEM_M590 -// #define TINY_GSM_ESP8266 - -// leave empty anything that does not apply -#define MY_GSM_APN "internet" -//#define MY_GSM_PIN "1234" -#define MY_GSM_USR "" -//If using a GSM modem, this stands for your GSM connection password. If using WiFi, it's your wireless password. -#define MY_GSM_PSW "" -//#define MY_GSM_SSID "" - -// Use Hardware Serial on Mega, Leonardo, Micro -//#define SerialAT Serial1 -// or Software Serial on Uno, Nano -#include -#define MY_GSM_RX 4 -#define MY_GSM_TX 5 - -// If your Mosquitto is old fashioned and does not support 3.1.1 -//#define MQTT_VERSION MQTT_VERSION_3_1 - -// Set this node's subscribe and publish topic prefix -#define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out" -#define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in" - -// Set MQTT client id -#define MY_MQTT_CLIENT_ID "mysensors-1" - -// Enable these if your MQTT broker requires usenrame/password -//#define MY_MQTT_USER "username" -//#define MY_MQTT_PASSWORD "password" - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -//#define MY_IP_ADDRESS 192,168,32,220 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,32,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// MQTT broker ip address or url. Define one or the other. -//#define MY_CONTROLLER_URL_ADDRESS "mymqttbroker.com" -#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 68 - -// The MQTT broker port to to open -#define MY_PORT 1883 - -/* -// Enable inclusion mode -#define MY_INCLUSION_MODE_FEATURE -// Enable Inclusion mode button on gateway -//#define MY_INCLUSION_BUTTON_FEATURE -// Set inclusion mode duration (in seconds) -#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -//#define MY_INCLUSION_MODE_BUTTON_PIN 3 - -// Set blinking period -#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Flash leds on rx/tx/err -// Uncomment to override default HW configurations -//#define MY_DEFAULT_ERR_LED_PIN 16 // Error led pin -//#define MY_DEFAULT_RX_LED_PIN 16 // Receive led pin -//#define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED -*/ - -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attached sensors data here -} - diff --git a/lib/MySensors/examples/GatewaySerial/GatewaySerial.ino b/lib/MySensors/examples/GatewaySerial/GatewaySerial.ino deleted file mode 100644 index 9b543fa0..00000000 --- a/lib/MySensors/examples/GatewaySerial/GatewaySerial.ino +++ /dev/null @@ -1,101 +0,0 @@ -/** -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -******************************* -* -* DESCRIPTION -* The ArduinoGateway prints data received from sensors on the serial link. -* The gateway accepts input on serial which will be sent out on radio network. -* -* The GW code is designed for Arduino Nano 328p / 16MHz -* -* Wire connections (OPTIONAL): -* - Inclusion button should be connected between digital pin 3 and GND -* - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series -* -* LEDs (OPTIONAL): -* - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs -* - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received -* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly -* - ERR (red) - fast blink on error during transmission error or receive crc error -* -*/ - -// Enable debug prints to serial monitor -#define MY_DEBUG - - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -// Set LOW transmit power level as default, if you have an amplified NRF-module and -// power your radio separately with a good regulator you can turn up PA level. -#define MY_RF24_PA_LEVEL RF24_PA_LOW - -// Enable serial gateway -#define MY_GATEWAY_SERIAL - -// Define a lower baud rate for Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender) -#if F_CPU == 8000000L -#define MY_BAUD_RATE 38400 -#endif - -// Enable inclusion mode -#define MY_INCLUSION_MODE_FEATURE -// Enable Inclusion mode button on gateway -//#define MY_INCLUSION_BUTTON_FEATURE - -// Inverses behavior of inclusion button (if using external pullup) -//#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP - -// Set inclusion mode duration (in seconds) -#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -//#define MY_INCLUSION_MODE_BUTTON_PIN 3 - -// Set blinking period -#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Inverses the behavior of leds -//#define MY_WITH_LEDS_BLINKING_INVERSE - -// Flash leds on rx/tx/err -// Uncomment to override default HW configurations -//#define MY_DEFAULT_ERR_LED_PIN 4 // Error led pin -//#define MY_DEFAULT_RX_LED_PIN 6 // Receive led pin -//#define MY_DEFAULT_TX_LED_PIN 5 // the PCB, on board LED - -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors -} - -void loop() -{ - // Send locally attached sensor data here -} diff --git a/lib/MySensors/examples/GatewaySerialRS485/GatewaySerialRS485.ino b/lib/MySensors/examples/GatewaySerialRS485/GatewaySerialRS485.ino deleted file mode 100644 index bf97470b..00000000 --- a/lib/MySensors/examples/GatewaySerialRS485/GatewaySerialRS485.ino +++ /dev/null @@ -1,104 +0,0 @@ -/** -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -******************************* -* -* DESCRIPTION -* The RS485 Gateway prints data received from sensors on the serial link. -* The gateway accepts input on seral which will be sent out on -* the RS485 link. -* -* Wire connections (OPTIONAL): -* - Inclusion button should be connected between digital pin 3 and GND -* - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series -* -* LEDs (OPTIONAL): -* - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received -* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly -* - ERR (red) - fast blink on error during transmission error or receive crc error -* -* If your Arduino board has additional serial ports -* you can use to connect the RS485 module. -* Otherwise, the gateway uses AltSoftSerial to handle two serial -* links on one Arduino. Use the following pins for RS485 link -* -* Board Transmit Receive PWM Unusable -* ----- -------- ------- ------------ -* Teensy 3.0 & 3.1 21 20 22 -* Teensy 2.0 9 10 (none) -* Teensy++ 2.0 25 4 26, 27 -* Arduino Uno 9 8 10 -* Arduino Leonardo 5 13 (none) -* Arduino Mega 46 48 44, 45 -* Wiring-S 5 6 4 -* Sanguino 13 14 12 -* -*/ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable RS485 transport layer -#define MY_RS485 - -// Define this to enables DE-pin management on defined pin -#define MY_RS485_DE_PIN 2 - -// Set RS485 baud rate to use -#define MY_RS485_BAUD_RATE 9600 - -// Enable this if RS485 is connected to a hardware serial port -//#define MY_RS485_HWSERIAL Serial1 - -// Enable serial gateway -#define MY_GATEWAY_SERIAL - - -// Enable inclusion mode -#define MY_INCLUSION_MODE_FEATURE -// Enable Inclusion mode button on gateway -#define MY_INCLUSION_BUTTON_FEATURE -// Set inclusion mode duration (in seconds) -#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -#define MY_INCLUSION_MODE_BUTTON_PIN 3 - -// Set blinking period -#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Flash leds on rx/tx/err -#define MY_DEFAULT_ERR_LED_PIN 4 // Error led pin -#define MY_DEFAULT_RX_LED_PIN 5 // Receive led pin -#define MY_DEFAULT_TX_LED_PIN 6 // the PCB, on board LED - -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors -} - -void loop() -{ - // Send locally attached sensor data here -} diff --git a/lib/MySensors/examples/GatewayW5100/GatewayW5100.ino b/lib/MySensors/examples/GatewayW5100/GatewayW5100.ino deleted file mode 100644 index 9c9097ae..00000000 --- a/lib/MySensors/examples/GatewayW5100/GatewayW5100.ino +++ /dev/null @@ -1,142 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * Contribution by a-lurker and Anticimex - * Contribution by Norbert Truchsess - * Contribution by Tomas Hozza - * - * - * DESCRIPTION - * The EthernetGateway sends data received from sensors to the ethernet link. - * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. - * - * The GW code is designed for Arduino 328p / 16MHz. ATmega168 does not have enough memory to run this program. - * - * LED purposes: - * - To use the feature, uncomment MY_DEFAULT_xxx_LED_PIN in the sketch below - * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received - * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly - * - ERR (red) - fast blink on error during transmission error or receive crc error - * - * See http://www.mysensors.org/build/ethernet_gateway for wiring instructions. - * - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -// Enable gateway ethernet module type -#define MY_GATEWAY_W5100 - -// W5100 Ethernet module SPI enable (optional if using a shield/module that manages SPI_EN signal) -//#define MY_W5100_SPI_EN 4 - -// Enable Soft SPI for NRF radio (note different radio wiring is required) -// The W5100 ethernet module seems to have a hard time co-operate with -// radio on the same spi bus. -#if !defined(MY_W5100_SPI_EN) && !defined(ARDUINO_ARCH_SAMD) -#define MY_SOFTSPI -#define MY_SOFT_SPI_SCK_PIN 14 -#define MY_SOFT_SPI_MISO_PIN 16 -#define MY_SOFT_SPI_MOSI_PIN 15 -#endif - -// When W5100 is connected we have to move CE/CSN pins for NRF radio -#ifndef MY_RF24_CE_PIN -#define MY_RF24_CE_PIN 5 -#endif -#ifndef MY_RF24_CS_PIN -#define MY_RF24_CS_PIN 6 -#endif - -// Enable UDP communication -//#define MY_USE_UDP // If using UDP you need to set MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS below - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -#define MY_IP_ADDRESS 192,168,178,66 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,178,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// Renewal period if using DHCP -//#define MY_IP_RENEWAL_INTERVAL 60000 - -// The port to keep open on node server mode / or port to contact in client mode -#define MY_PORT 5003 - -// Controller ip address. Enables client mode (default is "server" mode). -// Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere. -//#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254 -//#define MY_CONTROLLER_URL_ADDRESS "my.controller.org" - -// The MAC address can be anything you want but should be unique on your network. -// Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. -// Note that most of the Arduino examples use "DEAD BEEF FEED" for the MAC address. -#define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED - - -// Enable inclusion mode -#define MY_INCLUSION_MODE_FEATURE -// Enable Inclusion mode button on gateway -//#define MY_INCLUSION_BUTTON_FEATURE -// Set inclusion mode duration (in seconds) -#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -//#define MY_INCLUSION_MODE_BUTTON_PIN 3 - -// Set blinking period -#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Flash leds on rx/tx/err -// Uncomment to override default HW configurations -//#define MY_DEFAULT_ERR_LED_PIN 7 // Error led pin -//#define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin -//#define MY_DEFAULT_TX_LED_PIN 9 // Transmit led pin - -#if defined(MY_USE_UDP) -#include -#endif -#include -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attached sensors data here -} - diff --git a/lib/MySensors/examples/GatewayW5100MQTTClient/GatewayW5100MQTTClient.ino b/lib/MySensors/examples/GatewayW5100MQTTClient/GatewayW5100MQTTClient.ino deleted file mode 100644 index 9c5a6b2b..00000000 --- a/lib/MySensors/examples/GatewayW5100MQTTClient/GatewayW5100MQTTClient.ino +++ /dev/null @@ -1,154 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * - * DESCRIPTION - * The W5100 MQTT gateway sends radio network (or locally attached sensors) data to your MQTT broker. - * The node also listens to MY_MQTT_TOPIC_PREFIX and sends out those messages to the radio network - * - * LED purposes: - * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h - * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received - * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly - * - ERR (red) - fast blink on error during transmission error or receive crc error - * - * See http://www.mysensors.org/build/esp8266_gateway for wiring instructions. - * nRF24L01+ ESP8266 - * VCC VCC - * CE GPIO4 - * CSN/CS GPIO15 - * SCK GPIO14 - * MISO GPIO12 - * MOSI GPIO13 - * - * Not all ESP8266 modules have all pins available on their external interface. - * This code has been tested on an ESP-12 module. - * The ESP8266 requires a certain pin configuration to download code, and another one to run code: - * - Connect REST (reset) via 10K pullup resistor to VCC, and via switch to GND ('reset switch') - * - Connect GPIO15 via 10K pulldown resistor to GND - * - Connect CH_PD via 10K resistor to VCC - * - Connect GPIO2 via 10K resistor to VCC - * - Connect GPIO0 via 10K resistor to VCC, and via switch to GND ('bootload switch') - * - * Inclusion mode button: - * - Connect GPIO5 via switch to GND ('inclusion switch') - * - * Hardware SHA204 signing is currently not supported! - * - * Make sure to fill in your ssid and WiFi password below for ssid & pass. - */ - - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enables and select radio type (if attached) -#define MY_RADIO_RF24 -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_GATEWAY_MQTT_CLIENT - -// Set this node's subscribe and publish topic prefix -#define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out" -#define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in" - -// Set MQTT client id -#define MY_MQTT_CLIENT_ID "mysensors-1" - -// W5100 Ethernet module SPI enable (optional if using a shield/module that manages SPI_EN signal) -//#define MY_W5100_SPI_EN 4 - -// Enable Soft SPI for NRF radio (note different radio wiring is required) -// The W5100 ethernet module seems to have a hard time co-operate with -// radio on the same spi bus. -#if !defined(MY_W5100_SPI_EN) && !defined(ARDUINO_ARCH_SAMD) -#define MY_SOFTSPI -#define MY_SOFT_SPI_SCK_PIN 14 -#define MY_SOFT_SPI_MISO_PIN 16 -#define MY_SOFT_SPI_MOSI_PIN 15 -#endif - -// When W5100 is connected we have to move CE/CSN pins for NRF radio -#ifndef MY_RF24_CE_PIN -#define MY_RF24_CE_PIN 5 -#endif -#ifndef MY_RF24_CS_PIN -#define MY_RF24_CS_PIN 6 -#endif - -// Enable these if your MQTT broker requires username/password -//#define MY_MQTT_USER "username" -//#define MY_MQTT_PASSWORD "password" - -// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) -#define MY_IP_ADDRESS 192,168,178,87 - -// If using static ip you can define Gateway and Subnet address as well -//#define MY_IP_GATEWAY_ADDRESS 192,168,178,1 -//#define MY_IP_SUBNET_ADDRESS 255,255,255,0 - -// MQTT broker ip address or url. Define one or the other. -//#define MY_CONTROLLER_URL_ADDRESS "m20.cloudmqtt.com" -#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 68 - -// The MQTT broker port to to open -#define MY_PORT 1883 - -/* -// Enable inclusion mode -#define MY_INCLUSION_MODE_FEATURE -// Enable Inclusion mode button on gateway -//#define MY_INCLUSION_BUTTON_FEATURE -// Set inclusion mode duration (in seconds) -#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -//#define MY_INCLUSION_MODE_BUTTON_PIN 3 - -// Set blinking period -#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Flash leds on rx/tx/err -// Uncomment to override default HW configurations -//#define MY_DEFAULT_ERR_LED_PIN 16 // Error led pin -//#define MY_DEFAULT_RX_LED_PIN 16 // Receive led pin -//#define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED -*/ - -#include -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors here -} - -void loop() -{ - // Send locally attached sensors data here -} - diff --git a/lib/MySensors/examples/LightSensor/LightSensor.ino b/lib/MySensors/examples/LightSensor/LightSensor.ino deleted file mode 100644 index b27616c5..00000000 --- a/lib/MySensors/examples/LightSensor/LightSensor.ino +++ /dev/null @@ -1,70 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik EKblad - * - * DESCRIPTION - * Example sketch showing how to measure light level using a LM393 photo-resistor - * http://www.mysensors.org/build/light - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define CHILD_ID_LIGHT 0 -#define LIGHT_SENSOR_ANALOG_PIN 0 - -uint32_t SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) - -MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL); -int lastLightLevel; - - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Light Sensor", "1.0"); - - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); -} - -void loop() -{ - int16_t lightLevel = (1023-analogRead(LIGHT_SENSOR_ANALOG_PIN))/10.23; - Serial.println(lightLevel); - if (lightLevel != lastLightLevel) { - send(msg.set(lightLevel)); - lastLightLevel = lightLevel; - } - sleep(SLEEP_TIME); -} - - - diff --git a/lib/MySensors/examples/LogOTAGateway/LogOTAGateway.ino b/lib/MySensors/examples/LogOTAGateway/LogOTAGateway.ino deleted file mode 100644 index 4c1eccc0..00000000 --- a/lib/MySensors/examples/LogOTAGateway/LogOTAGateway.ino +++ /dev/null @@ -1,107 +0,0 @@ -/** -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -******************************* -* -* DESCRIPTION -* The ArduinoGateway prints data received from sensors on the serial link. -* The gateway accepts input on serial which will be sent out on radio network. -* -* The GW code is designed for Arduino Nano 328p / 16MHz -* -* Wire connections (OPTIONAL): -* - Inclusion button should be connected between digital pin 3 and GND -* - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series -* -* LEDs (OPTIONAL): -* - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs -* - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received -* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly -* - ERR (red) - fast blink on error during transmission error or receive crc error -* -* OTA DEBUG MESSAGES -* - Add the OTADebugReceive(message) into receive(const MyMessage &message) on a serial connected node -* - Add '#define MY_DEBUG_OTA (0)' to your Node sketch by replacing (0) with the node id of your serial connected node -* -*/ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable OTA log display -#define MY_OTA_LOG_RECEIVER_FEATURE - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -// Set LOW transmit power level as default, if you have an amplified NRF-module and -// power your radio separately with a good regulator you can turn up PA level. -#define MY_RF24_PA_LEVEL RF24_PA_LOW - -// Enable serial gateway -#define MY_GATEWAY_SERIAL - -// Define a lower baud rate for Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender) -#if F_CPU == 8000000L -#define MY_BAUD_RATE 38400 -#endif - -// Enable inclusion mode -#define MY_INCLUSION_MODE_FEATURE -// Enable Inclusion mode button on gateway -//#define MY_INCLUSION_BUTTON_FEATURE - -// Inverses behavior of inclusion button (if using external pullup) -//#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP - -// Set inclusion mode duration (in seconds) -#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -//#define MY_INCLUSION_MODE_BUTTON_PIN 3 - -// Set blinking period -#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Inverses the behavior of leds -//#define MY_WITH_LEDS_BLINKING_INVERSE - -// Flash leds on rx/tx/err -// Uncomment to override default HW configurations -//#define MY_DEFAULT_ERR_LED_PIN 4 // Error led pin -//#define MY_DEFAULT_RX_LED_PIN 6 // Receive led pin -//#define MY_DEFAULT_TX_LED_PIN 5 // the PCB, on board LED - -#include - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors -} - -void loop() -{ - // Send locally attached sensor data here -} diff --git a/lib/MySensors/examples/LogOTANode/LogOTANode.ino b/lib/MySensors/examples/LogOTANode/LogOTANode.ino deleted file mode 100644 index 8fd0d1b8..00000000 --- a/lib/MySensors/examples/LogOTANode/LogOTANode.ino +++ /dev/null @@ -1,74 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * Example for sending debug messages over the air (OTA). - * - */ - -// Enable debug -#define MY_DEBUG - -// Enable OTA debugging to Node 0 -#define MY_DEBUG_OTA (0) - -// Allow sending logs without MY_DEBUG_OTA enabled -#define MY_OTA_LOG_SENDER_FEATURE - -// Disable echoing of debug messages -//#define MY_DEBUG_OTA_DISABLE_ECHO - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -void setup() -{ -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("DebugSensor", "1.0"); -} - -// Arduino loop -int c=0; -void loop() -{ - // Wait some time - if (sleep(3000)==MY_SLEEP_NOT_POSSIBLE) { - delay(3000); - } - - // Count loops - c++; - - // A debug message - DEBUG_OUTPUT(PSTR("DEBUG\nc=%" PRId16 "\nmillis=%" PRId32 "\n"), c, hwMillis()); - - // Send a log message to a node, requesting that the message is echoed back to this node - OTALog(0, true, PSTR("LOG\nc=%" PRId16 "\nmillis=%" PRId32 "\n"), c, hwMillis()); -} diff --git a/lib/MySensors/examples/MockMySensors/MockMySensors.ino b/lib/MySensors/examples/MockMySensors/MockMySensors.ino deleted file mode 100644 index 687be8e8..00000000 --- a/lib/MySensors/examples/MockMySensors/MockMySensors.ino +++ /dev/null @@ -1,1515 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Barduino 2015, GizMoCuz 2015 - * - * DESCRIPTION - * This sketch is intended to create fake sensors which register and respond to the controller - * - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#define MY_NODE_ID 254 - -#include - -#define RADIO_ERROR_LED_PIN 4 // Error led pin -#define RADIO_RX_LED_PIN 6 // Receive led pin -#define RADIO_TX_LED_PIN 5 // the PCB, on board LED - -// Wait times -#define LONG_WAIT 500 -#define SHORT_WAIT 50 - -#define SKETCH_NAME "MockMySensors " -#define SKETCH_VERSION "v0.5" - -// Define Sensors ids -/* S_DOOR, S_MOTION, S_SMOKE, S_LIGHT, S_DIMMER, S_COVER, S_TEMP, S_HUM, S_BARO, S_WIND, - S_RAIN, S_UV, S_WEIGHT, S_POWER, S_HEATER, S_DISTANCE, S_LIGHT_LEVEL, S_ARDUINO_NODE, - S_ARDUINO_REPEATER_NODE, S_LOCK, S_IR, S_WATER, S_AIR_QUALITY, S_CUSTOM, S_DUST, - S_SCENE_CONTROLLER -*/ - -////#define ID_S_ARDUINO_NODE //auto defined in initialization -////#define ID_S_ARDUINO_REPEATER_NODE //auto defined in initialization - - -// Some of these ID's have not been updated for v1.5. Uncommenting too many of them -// will make the sketch too large for a pro mini's memory so it's probably best to try -// one at a time. - -#define ID_S_ARMED 0 // dummy to control armed stated for several sensors -#define ID_S_DOOR 1 -//#define ID_S_MOTION 2 -//#define ID_S_SMOKE 3 -//#define ID_S_LIGHT 4 -//#define ID_S_DIMMER 5 -//#define ID_S_COVER 6 -//#define ID_S_TEMP 7 -//#define ID_S_HUM 8 -//#define ID_S_BARO 9 -//#define ID_S_WIND 10 -//#define ID_S_RAIN 11 -//#define ID_S_UV 12 -//#define ID_S_WEIGHT 13 -//#define ID_S_POWER 14 -//#define ID_S_HEATER 15 -//#define ID_S_DISTANCE 16 -//#define ID_S_LIGHT_LEVEL 17 -//#define ID_S_LOCK 18 -//#define ID_S_IR 19 -//#define ID_S_WATER 20 -//#define ID_S_AIR_QUALITY 21 -//#define ID_S_DUST 22 -//#define ID_S_SCENE_CONTROLLER 23 -//// Lib 1.5 sensors -//#define ID_S_RGB_LIGHT 24 -//#define ID_S_RGBW_LIGHT 25 -//#define ID_S_COLOR_SENSOR 26 -//#define ID_S_HVAC 27 -//#define ID_S_MULTIMETER 28 -//#define ID_S_SPRINKLER 29 -//#define ID_S_WATER_LEAK 30 -//#define ID_S_SOUND 31 -//#define ID_S_VIBRATION 32 -//#define ID_S_MOISTURE 33 -// -//#define ID_S_CUSTOM 99 - - - -// Global Vars -uint32_t SLEEP_TIME = 900000; // Sleep time between reads (in milliseconds) -bool metric = true; -long randNumber; - - -//Instantiate Messages objects - -#ifdef ID_S_ARMED -bool isArmed; -#endif - -#ifdef ID_S_DOOR // V_TRIPPED, V_ARMED -MyMessage msg_S_DOOR_T(ID_S_DOOR,V_TRIPPED); -MyMessage msg_S_DOOR_A(ID_S_DOOR,V_ARMED); -#endif - -#ifdef ID_S_MOTION // V_TRIPPED, V_ARMED -MyMessage msg_S_MOTION_A(ID_S_MOTION,V_ARMED); -MyMessage msg_S_MOTION_T(ID_S_MOTION,V_TRIPPED); -#endif - -#ifdef ID_S_SMOKE // V_TRIPPED, V_ARMED -MyMessage msg_S_SMOKE_T(ID_S_SMOKE,V_TRIPPED); -MyMessage msg_S_SMOKE_A(ID_S_SMOKE,V_ARMED); -#endif - -#ifdef ID_S_LIGHT -MyMessage msg_S_LIGHT(ID_S_LIGHT,V_LIGHT); -bool isLightOn=0; -#endif - -#ifdef ID_S_DIMMER -MyMessage msg_S_DIMMER(ID_S_DIMMER,V_DIMMER); -int dimmerVal=100; -#endif - -#ifdef ID_S_COVER -MyMessage msg_S_COVER_U(ID_S_COVER,V_UP); -MyMessage msg_S_COVER_D(ID_S_COVER,V_DOWN); -MyMessage msg_S_COVER_S(ID_S_COVER,V_STOP); -MyMessage msg_S_COVER_V(ID_S_COVER,V_VAR1); -int coverState=0; //0=Stop; 1=up; -1=down -#endif - -#ifdef ID_S_TEMP -MyMessage msg_S_TEMP(ID_S_TEMP,V_TEMP); -#endif - -#ifdef ID_S_HUM -MyMessage msg_S_HUM(ID_S_HUM,V_HUM); -#endif - -#ifdef ID_S_BARO -MyMessage msg_S_BARO_P(ID_S_BARO,V_PRESSURE); -MyMessage msg_S_BARO_F(ID_S_BARO,V_FORECAST); -#endif - -#ifdef ID_S_WIND -MyMessage msg_S_WIND_S(ID_S_WIND,V_WIND); -MyMessage msg_S_WIND_G(ID_S_WIND,V_GUST); -MyMessage msg_S_WIND_D(ID_S_WIND,V_DIRECTION); -#endif - -#ifdef ID_S_RAIN -MyMessage msg_S_RAIN_A(ID_S_RAIN,V_RAIN); -MyMessage msg_S_RAIN_R(ID_S_RAIN,V_RAINRATE); -#endif - -#ifdef ID_S_UV -MyMessage msg_S_UV(ID_S_UV,V_UV); -#endif - -#ifdef ID_S_WEIGHT -MyMessage msg_S_WEIGHT(ID_S_WEIGHT,V_WEIGHT); -#endif - -#ifdef ID_S_POWER -MyMessage msg_S_POWER_W(ID_S_POWER,V_WATT); -MyMessage msg_S_POWER_K(ID_S_POWER,V_KWH); -#endif - - -#ifdef ID_S_HEATER - -//////// REVIEW IMPLEMENTATION //////////// - -MyMessage msg_S_HEATER_SET_POINT(ID_S_HEATER, - V_HVAC_SETPOINT_HEAT); // HVAC/Heater setpoint (Integer between 0-100). S_HEATER, S_HVAC -MyMessage msg_S_HEATER_FLOW_STATE(ID_S_HEATER, - V_HVAC_FLOW_STATE); // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" // S_HVAC, S_HEATER - -//MyMessage msg_S_HEATER_STATUS(ID_S_HEATER,V_STATUS); -//MyMessage msg_S_HEATER_TEMP(ID_S_HEATER,V_TEMP); - -float heater_setpoint=21.5; -String heater_flow_state="Off"; - -// float heater_temp=23.5; -// bool heater_status=false; - - -// V_TEMP // Temperature -// V_STATUS // Binary status. 0=off 1=on -// V_HVAC_FLOW_STATE // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" -// V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") -// V_HVAC_SETPOINT_HEAT // HVAC/Heater setpoint -#endif - -#ifdef ID_S_DISTANCE -MyMessage msg_S_DISTANCE(ID_S_DISTANCE,V_DISTANCE); -#endif - -#ifdef ID_S_LIGHT_LEVEL -MyMessage msg_S_LIGHT_LEVEL(ID_S_LIGHT_LEVEL,V_LIGHT_LEVEL); -#endif - -#ifdef ID_S_LOCK -MyMessage msg_S_LOCK(ID_S_LOCK,V_LOCK_STATUS); -bool isLocked = 0; -#endif - -#ifdef ID_S_IR -MyMessage msg_S_IR_S(ID_S_IR,V_IR_SEND); -MyMessage msg_S_IR_R(ID_S_IR,V_IR_RECEIVE); -long irVal = 0; -#endif - -#ifdef ID_S_WATER -MyMessage msg_S_WATER_F(ID_S_WATER,V_FLOW); -MyMessage msg_S_WATER_V(ID_S_WATER,V_VOLUME); -#endif - -#ifdef ID_S_AIR_QUALITY -MyMessage msg_S_AIR_QUALITY(ID_S_AIR_QUALITY,V_LEVEL); -#endif - -#ifdef ID_S_DUST -MyMessage msg_S_DUST(ID_S_DUST,V_LEVEL); -#endif - -#ifdef ID_S_SCENE_CONTROLLER -MyMessage msg_S_SCENE_CONTROLLER_ON(ID_S_SCENE_CONTROLLER,V_SCENE_ON); -MyMessage msg_S_SCENE_CONTROLLER_OF(ID_S_SCENE_CONTROLLER,V_SCENE_OFF); -// not sure if scene controller sends int or chars -// betting on ints as Touch Display Scen by Hek // compiler warnings -char *scenes[] = { - (char *)"Good Morning", - (char *)"Clean Up!", - (char *)"All Lights Off", - (char *)"Music On/Off" -}; - -int sceneVal=0; -int sceneValPrevious=0; - -#endif - -#ifdef ID_S_RGB_LIGHT -MyMessage msg_S_RGB_LIGHT_V_RGB(ID_S_RGB_LIGHT,V_RGB); -MyMessage msg_S_RGB_LIGHT_V_WATT(ID_S_RGB_LIGHT,V_WATT); -String rgbState="000000"; -//RGB light V_RGB, V_WATT -//RGB value transmitted as ASCII hex string (I.e "ff0000" for red) -#endif - -#ifdef ID_S_RGBW_LIGHT -MyMessage msg_S_RGBW_LIGHT_V_RGBW(ID_S_RGBW_LIGHT,V_RGBW); -MyMessage msg_S_RGBW_LIGHT_V_WATT(ID_S_RGBW_LIGHT,V_WATT); -String rgbwState="00000000"; -//RGBW light (with separate white component) V_RGBW, V_WATT -//RGBW value transmitted as ASCII hex string (I.e "ff0000ff" for red + full white) S_RGBW_LIGHT -#endif - -#ifdef ID_S_COLOR_SENSOR -MyMessage msg_S_COLOR_SENSOR_V_RGB(ID_S_COLOR_SENSOR,V_RGB); -//Color sensor V_RGB -//RGB value transmitted as ASCII hex string (I.e "ff0000" for red) S_RGB_LIGHT, S_COLOR_SENSOR -#endif - -#ifdef ID_S_HVAC -MyMessage msg_S_HVAC_V_HVAC_SETPOINT_HEAT(ID_S_HVAC,V_HVAC_SETPOINT_HEAT); -MyMessage msg_S_HVAC_V_HVAC_SETPOINT_COOL(ID_S_HVAC,V_HVAC_SETPOINT_COOL); -MyMessage msg_S_HVAC_V_HVAC_FLOW_STATET(ID_S_HVAC,V_HVAC_FLOW_STATE); -MyMessage msg_S_HVAC_V_HVAC_FLOW_MODE(ID_S_HVAC,V_HVAC_FLOW_MODE); -MyMessage msg_S_HVAC_V_HVAC_SPEED(ID_S_HVAC,V_HVAC_SPEED); - -float hvac_SetPointHeat = 16.5; -float hvac_SetPointCool = 25.5; -String hvac_FlowState = "AutoChangeOver"; -String hvac_FlowMode = "Auto"; -String hvac_Speed = "Normal"; - -//Thermostat/HVAC device -//V_HVAC_SETPOINT_HEAT, // HVAC/Heater setpoint -//V_HVAC_SETPOINT_COOL, // HVAC cold setpoint -//V_HVAC_FLOW_STATE, // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" -//V_HVAC_FLOW_MODE, // Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn") -//V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") - -// NOT IMPLEMENTED YET -//V_TEMP // Temperature -//V_STATUS // Binary status. 0=off 1=on -#endif - -#ifdef ID_S_MULTIMETER -MyMessage msg_S_MULTIMETER_V_IMPEDANCE(ID_S_MULTIMETER,V_IMPEDANCE); -MyMessage msg_S_MULTIMETER_V_VOLTAGE(ID_S_MULTIMETER,V_VOLTAGE); -MyMessage msg_S_MULTIMETER_V_CURRENT(ID_S_MULTIMETER,V_CURRENT); - -// Multimeter device V_VOLTAGE, V_CURRENT, V_IMPEDANCE -// V_IMPEDANCE 14 Impedance value -// V_VOLTAGE 38 Voltage level -// V_CURRENT 39 Current level -#endif - -#ifdef ID_S_SPRINKLER -// S_SPRINKLER 31 Sprinkler device V_STATUS (turn on/off), V_TRIPPED (if fire detecting device) -// V_STATUS 2 Binary status. 0=off 1=on -// V_ARMED 15 Armed status of a security sensor. 1=Armed, 0=Bypassed -// V_TRIPPED 16 Tripped status of a security sensor. 1=Tripped, 0=Untripped -#endif - -#ifdef ID_S_WATER_LEAK -#endif -#ifdef ID_S_SOUND -#endif -#ifdef ID_S_VIBRATION -#endif -#ifdef ID_S_MOISTURE -#endif - -#ifdef ID_S_MOISTURE -MyMessage msg_S_MOISTURE(ID_S_MOISTURE,V_LEVEL); -#endif - -#ifdef ID_S_CUSTOM -MyMessage msg_S_CUSTOM_1(ID_S_CUSTOM,V_VAR1); -MyMessage msg_S_CUSTOM_2(ID_S_CUSTOM,V_VAR2); -MyMessage msg_S_CUSTOM_3(ID_S_CUSTOM,V_VAR3); -MyMessage msg_S_CUSTOM_4(ID_S_CUSTOM,V_VAR4); -MyMessage msg_S_CUSTOM_5(ID_S_CUSTOM,V_VAR5); -#endif - - - - -void setup() -{ - // Random SEED - randomSeed(analogRead(0)); - - wait(LONG_WAIT); - Serial.println("GW Started"); -} - -void presentation() -{ - // Send the Sketch Version Information to the Gateway - Serial.print("Send Sketch Info: "); - sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); - Serial.print(SKETCH_NAME); - Serial.println(SKETCH_VERSION); - wait(LONG_WAIT); - - // Get controller configuration - Serial.print("Get Config: "); - metric = getControllerConfig().isMetric; - Serial.println(metric ? "Metric":"Imperial"); - wait(LONG_WAIT); - - // Init Armed -#ifdef ID_S_ARMED - isArmed = true; -#endif - - // Register all sensors to gw (they will be created as child devices) - Serial.println("Presenting Nodes"); - Serial.println("________________"); - -#ifdef ID_S_DOOR - Serial.println(" S_DOOR"); - present(ID_S_DOOR,S_DOOR,"Outside Door"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_MOTION - Serial.println(" S_MOTION"); - present(ID_S_MOTION,S_MOTION,"Outside Motion"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_SMOKE - Serial.println(" S_SMOKE"); - present(ID_S_SMOKE,S_SMOKE,"Kitchen Smoke"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_LIGHT - Serial.println(" S_LIGHT"); - present(ID_S_LIGHT,S_LIGHT,"Hall Light"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_DIMMER - Serial.println(" S_DIMMER"); - present(ID_S_DIMMER,S_DIMMER,"Living room dimmer"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_COVER - Serial.println(" S_COVER"); - present(ID_S_COVER,S_COVER,"Window cover"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_TEMP - Serial.println(" S_TEMP"); - present(ID_S_TEMP,S_TEMP,"House Temperarue"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_HUM - Serial.println(" S_HUM"); - present(ID_S_HUM,S_HUM,"Current Humidity"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_BARO - Serial.println(" S_BARO"); - present(ID_S_BARO,S_BARO," Air pressure"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_WIND - Serial.println(" S_WIND"); - present(ID_S_WIND,S_WIND,"Wind Station"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_RAIN - Serial.println(" S_RAIN"); - present(ID_S_RAIN,S_RAIN,"Rain Station"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_UV - Serial.println(" S_UV"); - present(ID_S_UV,S_UV,"Ultra Violet"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_WEIGHT - Serial.println(" S_WEIGHT"); - present(ID_S_WEIGHT,S_WEIGHT,"Outdoor Scale"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_POWER - Serial.println(" S_POWER"); - present(ID_S_POWER,S_POWER,"Power Metric"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_HEATER - Serial.println(" S_HEATER"); - present(ID_S_HEATER,S_HEATER,"Garage Heater"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_DISTANCE - Serial.println(" S_DISTANCE"); - present(ID_S_DISTANCE,S_DISTANCE,"Distance Measure"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_LIGHT_LEVEL - Serial.println(" S_LIGHT_LEVEL"); - present(ID_S_LIGHT_LEVEL,S_LIGHT_LEVEL,"Outside Light Level"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_LOCK - Serial.println(" S_LOCK"); - present(ID_S_LOCK,S_LOCK,"Front Door Lock"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_IR - Serial.println(" S_IR"); - present(ID_S_IR,S_IR,"Univeral Command"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_WATER - Serial.println(" S_WATER"); - present(ID_S_WATER,S_WATER,"Water Level"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_AIR_QUALITY - Serial.println(" S_AIR_QUALITY"); - present(ID_S_AIR_QUALITY,S_AIR_QUALITY,"Air Station"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_DUST - Serial.println(" S_DUST"); - present(ID_S_DUST,S_DUST,"Dust Level"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_SCENE_CONTROLLER - Serial.println(" S_SCENE_CONTROLLER"); - present(ID_S_SCENE_CONTROLLER,S_SCENE_CONTROLLER,"Scene Controller"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_RGB_LIGHT - Serial.println(" RGB_LIGHT"); - present(ID_S_RGB_LIGHT,S_RGB_LIGHT,"Mood Light"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_RGBW_LIGHT - Serial.println(" RGBW_LIGHT"); - present(ID_S_RGBW_LIGHT,S_RGBW_LIGHT,"Mood Light 2"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_COLOR_SENSOR - Serial.println(" COLOR_SENSOR"); - present(ID_S_COLOR_SENSOR,S_COLOR_SENSOR,"Hall Painting"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_HVAC - Serial.println(" HVAC"); - present(ID_S_HVAC,S_HVAC,"HVAC"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_MULTIMETER - Serial.println(" MULTIMETER"); - present(ID_S_MULTIMETER,S_MULTIMETER,"Electric Staion"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_SPRINKLER -#endif -#ifdef ID_S_WATER_LEAK -#endif -#ifdef ID_S_SOUND -#endif -#ifdef ID_S_VIBRATION -#endif -#ifdef ID_S_MOISTURE -#endif - -#ifdef ID_S_MOISTURE - Serial.println(" S_MOISTURE"); - present(ID_S_MOISTURE,S_MOISTURE,"Basement Sensor"); - wait(SHORT_WAIT); -#endif - -#ifdef ID_S_CUSTOM - Serial.println(" S_CUSTOM"); - present(ID_S_CUSTOM,S_CUSTOM,"Other Stuff"); - wait(SHORT_WAIT); -#endif - - - - Serial.println("________________"); - -} - -void loop() -{ - Serial.println(""); - Serial.println(""); - Serial.println(""); - Serial.println("#########################"); - randNumber=random(0,101); - - Serial.print("RandomNumber:"); - Serial.println(randNumber); - // Send fake battery level - Serial.println("Send Battery Level"); - sendBatteryLevel(randNumber); - wait(LONG_WAIT); - - // Request time - Serial.println("Request Time"); - requestTime(); - wait(LONG_WAIT); - - //Read Sensors -#ifdef ID_S_DOOR - door(); -#endif - -#ifdef ID_S_MOTION - motion(); -#endif - -#ifdef ID_S_SMOKE - smoke(); -#endif - -#ifdef ID_S_LIGHT - light(); -#endif - -#ifdef ID_S_DIMMER - dimmer(); -#endif - -#ifdef ID_S_COVER - cover(); -#endif - -#ifdef ID_S_TEMP - temp(); -#endif - -#ifdef ID_S_HUM - hum(); -#endif - -#ifdef ID_S_BARO - baro(); -#endif - -#ifdef ID_S_WIND - wind(); -#endif - -#ifdef ID_S_RAIN - rain(); -#endif - -#ifdef ID_S_UV - uv(); -#endif - -#ifdef ID_S_WEIGHT - weight(); -#endif - -#ifdef ID_S_POWER - power(); -#endif - -#ifdef ID_S_HEATER - heater(); -#endif - -#ifdef ID_S_DISTANCE - distance(); -#endif - -#ifdef ID_S_LIGHT_LEVEL - light_level(); -#endif - -#ifdef ID_S_LOCK - lock(); -#endif - -#ifdef ID_S_IR - ir(); -#endif - -#ifdef ID_S_WATER - water(); -#endif - -#ifdef ID_S_AIR_QUALITY - air(); -#endif - -#ifdef ID_S_DUST - dust(); -#endif - -#ifdef ID_S_SCENE_CONTROLLER - scene(); -#endif - -#ifdef ID_S_RGB_LIGHT - rgbLight(); -#endif - -#ifdef ID_S_RGBW_LIGHT - rgbwLight(); -#endif - -#ifdef ID_S_COLOR_SENSOR - color(); -#endif - -#ifdef ID_S_HVAC - hvac(); -#endif - -#ifdef ID_S_MULTIMETER - multimeter(); -#endif - -#ifdef ID_S_SPRINKLER -#endif -#ifdef ID_S_WATER_LEAK -#endif -#ifdef ID_S_SOUND -#endif -#ifdef ID_S_VIBRATION -#endif -#ifdef ID_S_MOISTURE -#endif - -#ifdef ID_S_MOISTURE - moisture(); -#endif - -#ifdef ID_S_CUSTOM - custom(); -#endif - - sendBatteryLevel(randNumber); - wait(SHORT_WAIT); - Serial.println("#########################"); - wait(SLEEP_TIME); //sleep a bit -} - -// This is called when a new time value was received -void receiveTime(uint32_t controllerTime) -{ - - Serial.print("Time value received: "); - Serial.println(controllerTime); - -} - -//void door(){} - -#ifdef ID_S_DOOR -void door() -{ - - Serial.print("Door is: " ); - - if (randNumber <= 50) { - Serial.println("Open"); - send(msg_S_DOOR_T.set((int16_t)1)); - } else { - Serial.println("Closed"); - send(msg_S_DOOR_T.set((int16_t)0)); - } -#ifdef ID_S_ARMED - Serial.print("System is: " ); - Serial.println((isArmed ? "Armed":"Disarmed")); - send(msg_S_DOOR_A.set(isArmed)); -#endif -} -#endif - -#ifdef ID_S_MOTION -void motion() -{ - - Serial.print("Motion is: " ); - - if (randNumber <= 50) { - Serial.println("Active"); - send(msg_S_MOTION_T.set(1)); - } else { - Serial.println("Quiet"); - send(msg_S_MOTION_T.set(0)); - } - -#ifdef ID_S_ARMED - Serial.print("System is: " ); - Serial.println((isArmed ? "Armed":"Disarmed")); - send(msg_S_MOTION_A.set(isArmed)); -#endif -} -#endif - -#ifdef ID_S_SMOKE -void smoke() -{ - - Serial.print("Smoke is: " ); - - if (randNumber <= 50) { - Serial.println("Active"); - send(msg_S_SMOKE_T.set(1)); - } else { - Serial.println("Quiet"); - send(msg_S_SMOKE_T.set(0)); - } - -#ifdef ID_S_ARMED - Serial.print("System is: " ); - Serial.println((isArmed ? "Armed":"Disarmed")); - send(msg_S_SMOKE_A.set(isArmed)); -#endif - -} -#endif - -#ifdef ID_S_LIGHT -void light() -{ - - Serial.print("Light is: " ); - Serial.println((isLightOn ? "On":"Off")); - - send(msg_S_LIGHT.set(isLightOn)); - -} -#endif - -#ifdef ID_S_DIMMER -void dimmer() -{ - - Serial.print("Dimmer is set to: " ); - Serial.println(dimmerVal); - - send(msg_S_DIMMER.set(dimmerVal)); - -} -#endif - -#ifdef ID_S_COVER -void cover() -{ - - Serial.print("Cover is : " ); - - if (coverState == 1) { - Serial.println("Opening"); - send(msg_S_COVER_U.set(1)); - } else if (coverState == -1) { - Serial.println("Closing"); - send(msg_S_COVER_D.set(0)); - } else { - Serial.println("Idle"); - send(msg_S_COVER_S.set(-1)); - } - send(msg_S_COVER_V.set(coverState)); -} -#endif - -#ifdef ID_S_TEMP -void temp() -{ - - Serial.print("Temperature is: " ); - Serial.println(map(randNumber,1,100,0,45)); - - send(msg_S_TEMP.set(map(randNumber,1,100,0,45))); - -} -#endif - -#ifdef ID_S_HUM -void hum() -{ - - Serial.print("Humidity is: " ); - Serial.println(randNumber); - - send(msg_S_HUM.set(randNumber)); - -} -#endif - -#ifdef ID_S_BARO -void baro() -{ - - const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"}; - long pressure = map(randNumber,1,100,870,1086);// hPa? - int forecast = map(randNumber,1,100,0,5); - - Serial.print("Atmospheric Pressure is: " ); - Serial.println(pressure); - send(msg_S_BARO_P.set(pressure)); - - Serial.print("Weather forecast: " ); - Serial.println(weather[forecast]); - send(msg_S_BARO_F.set(weather[forecast])); - -} -#endif - -#ifdef ID_S_WIND -void wind() -{ - - Serial.print("Wind Speed is: " ); - Serial.println(randNumber); - send(msg_S_WIND_S.set(randNumber)); - - Serial.print("Wind Gust is: " ); - Serial.println(randNumber+10); - send(msg_S_WIND_G.set(randNumber+10)); - - Serial.print("Wind Direction is: " ); - Serial.println(map(randNumber,1,100,0,360)); - send(msg_S_WIND_D.set(map(randNumber,1,100,0,360))); - -} -#endif - -#ifdef ID_S_RAIN -void rain() -{ - - Serial.print("Rain amount is: " ); - Serial.println(randNumber); - - send(msg_S_RAIN_A.set(randNumber)); - - Serial.print("Rain rate is: " ); - Serial.println(randNumber/60); - - send(msg_S_RAIN_R.set(randNumber/60,1)); - -} -#endif - -#ifdef ID_S_UV -void uv() -{ - - Serial.print("Ultra Violet level is: " ); - Serial.println(map(randNumber,1,100,0,15)); - - send(msg_S_UV.set(map(randNumber,1,100,0,15))); - -} -#endif - -#ifdef ID_S_WEIGHT -void weight() -{ - - Serial.print("Weight is: " ); - Serial.println(map(randNumber,1,100,0,150)); - - send(msg_S_WEIGHT.set(map(randNumber,1,100,0,150))); - -} -#endif - -#ifdef ID_S_POWER -void power() -{ - - Serial.print("Watt is: " ); - Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_POWER_W.set(map(randNumber,1,100,0,150))); - - Serial.print("KWH is: " ); - Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_POWER_K.set(map(randNumber,1,100,0,150))); - -} -#endif - -#ifdef ID_S_HEATER -void heater() -{ - // float heater_setpoint=21.5; - // float heater_temp=23.5; - // bool heater_status=false; - // String heatState="Off"; - - Serial.print("Heater flow state is: " ); - Serial.println(heater_flow_state); - send(msg_S_HEATER_FLOW_STATE.set(heater_flow_state.c_str())); - - // Serial.print("Heater on/off is: " ); - // Serial.println((heater_status==true)?"On":"Off"); - // send(msg_S_HEATER_STATUS.set(heater_status)); - - // Serial.print("Heater Temperature is: " ); - // Serial.println(heater_temp,1); - // send(msg_S_HEATER_TEMP.set(heater_temp,1)); - - Serial.print("Heater Setpoint: " ); - Serial.println(heater_setpoint,1); - send(msg_S_HEATER_SET_POINT.set(heater_setpoint,1)); -} -#endif - -#ifdef ID_S_DISTANCE -void distance() -{ - - Serial.print("Distance is: " ); - Serial.println(map(randNumber,1,100,0,150)); - - send(msg_S_DISTANCE.set(map(randNumber,1,100,0,150))); - -} -#endif - -#ifdef ID_S_LIGHT_LEVEL -void light_level() -{ - - Serial.print("Light is: " ); - Serial.println(map(randNumber,1,100,0,150)); - - send(msg_S_LIGHT_LEVEL.set(map(randNumber,1,100,0,150))); - -} -#endif - -#ifdef ID_S_LOCK -void lock() -{ - - Serial.print("Lock is: " ); - Serial.println((isLocked ? "Locked":"Unlocked")); - send(msg_S_LOCK.set(isLocked)); - -} -#endif - -#ifdef ID_S_IR -void ir() -{ - - Serial.print("Infrared is: " ); - Serial.println(irVal); - - send(msg_S_IR_S.set(irVal)); - send(msg_S_IR_R.set(irVal)); - -} -#endif - -#ifdef ID_S_WATER -void water() -{ - - Serial.print("Water flow is: " ); - Serial.println(map(randNumber,1,100,0,150)); - - send(msg_S_WATER_F.set(map(randNumber,1,100,0,150))); - - Serial.print("Water volume is: " ); - Serial.println(map(randNumber,1,100,0,150)); - - send(msg_S_WATER_V.set(map(randNumber,1,100,0,150))); - -} -#endif - -#ifdef ID_S_AIR_QUALITY -void air() -{ - - Serial.print("Air Quality is: " ); - Serial.println(randNumber); - - send(msg_S_AIR_QUALITY.set(randNumber)); - -} -#endif - -#ifdef ID_S_DUST -void dust() -{ - - Serial.print("Dust level is: " ); - Serial.println(randNumber); - - send(msg_S_DUST.set(randNumber)); - -} -#endif - -#ifdef ID_S_SCENE_CONTROLLER -void scene() -{ - - Serial.print("Scene is: " ); - Serial.println(scenes[sceneVal]); - - if(sceneValPrevious != sceneVal) { - send(msg_S_SCENE_CONTROLLER_OF.set(sceneValPrevious)); - send(msg_S_SCENE_CONTROLLER_ON.set(sceneVal)); - sceneValPrevious=sceneVal; - } - -} -#endif - -#ifdef ID_S_RGB_LIGHT -void rgbLight() -{ - - Serial.print("RGB Light state is: " ); - Serial.println(rgbState); - send(msg_S_RGB_LIGHT_V_RGB.set(rgbState.c_str())); - - Serial.print("RGB Light Watt is: " ); - Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_RGB_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); - -} -#endif - -#ifdef ID_S_RGBW_LIGHT -void rgbwLight() -{ - - Serial.print("RGBW Light state is: " ); - Serial.println(rgbwState); - send(msg_S_RGBW_LIGHT_V_RGBW.set(rgbwState.c_str())); - - Serial.print("RGBW Light Watt is: " ); - Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_RGBW_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); - -} -#endif - -#ifdef ID_S_COLOR_SENSOR -void color() -{ - String colorState; - - String red = String(random(0,256),HEX); - String green = String(random(0,256),HEX); - String blue = String(random(0,256),HEX); - - colorState=String(red + green + blue); - - Serial.print("Color state is: " ); - Serial.println(colorState); - send(msg_S_COLOR_SENSOR_V_RGB.set(colorState.c_str())); - -} -#endif - -#ifdef ID_S_HVAC -void hvac() -{ - - // float hvac_SetPointHeat = 16.5; - // float hvac_SetPointCool = 25.5; - // String hvac_FlowState = "AutoChangeOver"; - // String hvac_FlowMode = "Auto"; - // String hvac_Speed = "Normal"; - - Serial.print("HVAC Set Point Heat is: " ); - Serial.println(hvac_SetPointHeat); - send(msg_S_HVAC_V_HVAC_SETPOINT_HEAT.set(hvac_SetPointHeat,1)); - - Serial.print("HVAC Set Point Cool is: " ); - Serial.println(hvac_SetPointCool); - send(msg_S_HVAC_V_HVAC_SETPOINT_COOL.set(hvac_SetPointCool,1)); - - Serial.print("HVAC Flow State is: " ); - Serial.println(hvac_FlowState); - send(msg_S_HVAC_V_HVAC_FLOW_STATET.set(hvac_FlowState.c_str())); - - Serial.print("HVAC Flow Mode is: " ); - Serial.println(hvac_FlowMode); - send(msg_S_HVAC_V_HVAC_FLOW_MODE.set(hvac_FlowMode.c_str())); - - Serial.print("HVAC Speed is: " ); - Serial.println(hvac_Speed); - send(msg_S_HVAC_V_HVAC_SPEED.set(hvac_Speed.c_str())); - -} -#endif - -#ifdef ID_S_MULTIMETER -void multimeter() -{ - int impedance=map(randNumber,1,100,0,15000); - int volt=map(randNumber,1,100,0,380); - int amps=map(randNumber,1,100,0,16); - - Serial.print("Impedance is: " ); - Serial.println(impedance); - send(msg_S_MULTIMETER_V_IMPEDANCE.set(impedance)); - - Serial.print("Voltage is: " ); - Serial.println(volt); - send(msg_S_MULTIMETER_V_VOLTAGE.set(volt)); - - Serial.print("Current is: " ); - Serial.println(amps); - send(msg_S_MULTIMETER_V_CURRENT.set(amps)); - -} -#endif - -#ifdef ID_S_SPRINKLER -#endif -#ifdef ID_S_WATER_LEAK -#endif -#ifdef ID_S_SOUND -#endif -#ifdef ID_S_VIBRATION -#endif -#ifdef ID_S_MOISTURE -#endif - -#ifdef ID_S_MOISTURE -void moisture() -{ - - Serial.print("Moisture level is: " ); - Serial.println(randNumber); - - send(msg_S_MOISTURE.set(randNumber)); -} -#endif - -#ifdef ID_S_CUSTOM -void custom() -{ - - Serial.print("Custom value is: " ); - Serial.println(randNumber); - - send(msg_S_CUSTOM_1.set(randNumber)); - send(msg_S_CUSTOM_2.set(randNumber)); - send(msg_S_CUSTOM_3.set(randNumber)); - send(msg_S_CUSTOM_4.set(randNumber)); - send(msg_S_CUSTOM_5.set(randNumber)); - -} -#endif - - -void receive(const MyMessage &message) -{ - switch (message.getType()) { -#ifdef ID_S_ARMED - case V_ARMED: - isArmed = message.getBool(); - Serial.print("Incoming change for ID_S_ARMED:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println((isArmed ? "Armed":"Disarmed" )); -#ifdef ID_S_DOOR - door();//temp ack for door -#endif -#ifdef ID_S_MOTION - motion();//temp ack -#endif -#ifdef ID_S_SMOKE - smoke();//temp ack -#endif - break; -#endif - - - case V_STATUS: // V_LIGHT: -#ifdef ID_S_LIGHT - if(message.getSensor()==ID_S_LIGHT) { - isLightOn = message.getBool(); - Serial.print("Incoming change for ID_S_LIGHT:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println((isLightOn ? "On":"Off")); - light(); // temp ack - } -#endif - // #ifdef ID_S_HEATER - // if(message.getSensor() == ID_S_HEATER){ - // heater_status = message.getBool(); - // Serial.print("Incoming change for ID_S_HEATER:"); - // Serial.print(message.getSensor()); - // Serial.print(", New status: "); - // Serial.println(heater_status); - // heater();//temp ack - // } - // #endif - break; - - -#ifdef ID_S_DIMMER - case V_DIMMER: - if ((message.getInt()<0)||(message.getInt()>100)) { - Serial.println( "V_DIMMER data invalid (should be 0..100)" ); - break; - } - dimmerVal= message.getInt(); - Serial.print("Incoming change for ID_S_DIMMER:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(message.getInt()); - dimmer();// temp ack - break; -#endif - -#ifdef ID_S_COVER - case V_UP: - coverState=1; - Serial.print("Incoming change for ID_S_COVER:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println("V_UP"); - cover(); // temp ack - break; - - case V_DOWN: - coverState=-1; - Serial.print("Incoming change for ID_S_COVER:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println("V_DOWN"); - cover(); //temp ack - break; - - case V_STOP: - coverState=0; - Serial.print("Incoming change for ID_S_COVER:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println("V_STOP"); - cover(); //temp ack - break; -#endif - - - case V_HVAC_SETPOINT_HEAT: - -#ifdef ID_S_HEATER - if(message.getSensor() == ID_S_HEATER) { - heater_setpoint=message.getFloat(); - - Serial.print("Incoming set point for ID_S_HEATER:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(heater_setpoint,1); - heater();//temp ack - } -#endif - -#ifdef ID_S_HVAC - if(message.getSensor() == ID_S_HVAC) { - hvac_SetPointHeat=message.getFloat(); - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(hvac_SetPointHeat,1); - hvac();//temp ack - } -#endif - break; - - case V_HVAC_FLOW_STATE: -#ifdef ID_S_HEATER - if(message.getSensor() == ID_S_HEATER) { - heater_flow_state=message.getString(); - Serial.print("Incoming flow state change for ID_S_HEATER:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(heater_flow_state); - heater();//temp ack - } -#endif - -#ifdef ID_S_HVAC - if(message.getSensor() == ID_S_HVAC) { - hvac_FlowState=message.getString(); - - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(hvac_FlowState); - hvac();//temp ack - } -#endif - break; - -#ifdef ID_S_LOCK - case V_LOCK_STATUS: - isLocked = message.getBool(); - Serial.print("Incoming change for ID_S_LOCK:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(message.getBool()?"Locked":"Unlocked"); - lock(); //temp ack - break; -#endif - -#ifdef ID_S_IR - case V_IR_SEND: - irVal = message.getLong(); - Serial.print("Incoming change for ID_S_IR:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(irVal); - ir(); // temp ack - break; - case V_IR_RECEIVE: - irVal = message.getLong(); - Serial.print("Incoming change for ID_S_IR:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(irVal); - ir(); // temp ack - break; -#endif - -#ifdef ID_S_SCENE_CONTROLLER - case V_SCENE_ON: - sceneVal = message.getInt(); - Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.print(scenes[sceneVal]); - Serial.println(" On"); - scene();// temp ack - break; - case V_SCENE_OFF: - sceneVal = message.getInt(); - Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.print(scenes[sceneVal]); - Serial.println(" Off"); - scene();// temp ack - break; -#endif - -#ifdef ID_S_RGB_LIGHT - case V_RGB: - rgbState=message.getString(); - Serial.print("Incoming flow state change for ID_S_RGB_LIGHT:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(rgbState); - rgbLight(); // temp ack - - break; -#endif - -#ifdef ID_S_RGBW_LIGHT - case V_RGBW: - rgbwState=message.getString(); - Serial.print("Incoming flow state change for ID_S_RGBW_LIGHT:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(rgbwState); - rgbwLight(); - break; -#endif - -#ifdef ID_S_HVAC - // hvac_SetPointHeat - // hvac_SetPointCool - // hvac_FlowState - // hvac_FlowMode - // hvac_Speed - - case V_HVAC_SETPOINT_COOL: - hvac_SetPointCool=message.getFloat(); - - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(hvac_SetPointCool,1); - hvac();//temp ack - break; - - case V_HVAC_FLOW_MODE: - hvac_Speed=message.getString(); - - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(hvac_Speed); - hvac();//temp ack - break; - - case V_HVAC_SPEED: - hvac_FlowMode=message.getString(); - - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(hvac_FlowMode); - hvac();//temp ack - break; -#endif - - default: - Serial.print("Unknown/Unimplemented message type: "); - Serial.println(message.getType()); - } - -} diff --git a/lib/MySensors/examples/MockMySensors/README.md b/lib/MySensors/examples/MockMySensors/README.md deleted file mode 100644 index 497b6d1a..00000000 --- a/lib/MySensors/examples/MockMySensors/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# MockMySensors -Arduino sketch to fake sensor for the MySensors Library - -This sketch is intended to create fake sensors which register and respond to the controller - -Barduino, GizMoCuz 2015 ------------------ - -Comment/Uncomment the sensors you would like to test - -Arduino Uno R3 can support about 12 sensors before it runs out of memory. -(turning off the MySensors debug helps if you are memory limited) - -With a Mega you can have them all - - -Changes Log ------------------ - -2015-09-07 -Five more sensors - S_RGB_LIGHT - S_RGBW_LIGHT - S_COLOR_SENSOR - S_HVAC - S_MULTIMETER -Consolidated HVAC and HEATER incoming message - -2015-09-06 - -Merge with Gizmocuz (implementation of S_HEATER & S_MOISTURE -Implementation of S_COVER, S_IR, S_SCENE_CONTROLLER - - -2015-08-19 - -Removed the load/save to eeprom -Touched the heater sensor -Created a pseudo sensor to handle the V_ARMED message. -All sensors which support V_ARMED will arm/disarm at the same time diff --git a/lib/MySensors/examples/MotionSensor/MotionSensor.ino b/lib/MySensors/examples/MotionSensor/MotionSensor.ino deleted file mode 100644 index 502215a5..00000000 --- a/lib/MySensors/examples/MotionSensor/MotionSensor.ino +++ /dev/null @@ -1,74 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * - * DESCRIPTION - * Motion Sensor example using HC-SR501 - * http://www.mysensors.org/build/motion - * - */ - -// Enable debug prints -// #define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -uint32_t SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds) -#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!) -#define CHILD_ID 1 // Id of the sensor child - -// Initialize motion message -MyMessage msg(CHILD_ID, V_TRIPPED); - -void setup() -{ - pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Motion Sensor", "1.0"); - - // Register all sensors to gw (they will be created as child devices) - present(CHILD_ID, S_MOTION); -} - -void loop() -{ - // Read digital motion value - bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; - - Serial.println(tripped); - send(msg.set(tripped?"1":"0")); // Send tripped value to gw - - // Sleep until interrupt comes in on motion sensor. Send update every two minute. - sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); -} - - diff --git a/lib/MySensors/examples/MotionSensorRS485/MotionSensorRS485.ino b/lib/MySensors/examples/MotionSensorRS485/MotionSensorRS485.ino deleted file mode 100644 index 96f0a18c..00000000 --- a/lib/MySensors/examples/MotionSensorRS485/MotionSensorRS485.ino +++ /dev/null @@ -1,98 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * - * DESCRIPTION - * This is an example of sensors using RS485 as transport layer - * - * Motion Sensor example using HC-SR501 - * http://www.mysensors.org/build/motion - * - * If your Arduino board has additional serial ports - * you can use to connect the RS485 module. - * Otherwise, the transport uses AltSoftSerial to handle two serial - * links on one Arduino. Use the following pins for RS485 link - * - * Board Transmit Receive PWM Unusable - * ----- -------- ------- ------------ - * Teensy 3.0 & 3.1 21 20 22 - * Teensy 2.0 9 10 (none) - * Teensy++ 2.0 25 4 26, 27 - * Arduino Uno 9 8 10 - * Arduino Leonardo 5 13 (none) - * Arduino Mega 46 48 44, 45 - * Wiring-S 5 6 4 - * Sanguino 13 14 12 * - * - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable RS485 transport layer -#define MY_RS485 - -// Define this to enables DE-pin management on defined pin -#define MY_RS485_DE_PIN 2 - -// Set RS485 baud rate to use -#define MY_RS485_BAUD_RATE 9600 - -// Enable this if RS485 is connected to a hardware serial port -//#define MY_RS485_HWSERIAL Serial1 - -#include - -uint32_t SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds) -#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!) -#define CHILD_ID 1 // Id of the sensor child - -// Initialize motion message -MyMessage msg(CHILD_ID, V_TRIPPED); - -void setup() -{ - pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Motion Sensor", "1.0"); - - // Register all sensors to gw (they will be created as child devices) - present(CHILD_ID, S_MOTION); -} - -void loop() -{ - // Read digital motion value - bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; - - Serial.println(tripped); - send(msg.set(tripped?"1":"0")); // Send tripped value to gw - - // Sleep until interrupt comes in on motion sensor. Send update every two minute. - sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); -} - - diff --git a/lib/MySensors/examples/Node2Node/Node2Node.ino b/lib/MySensors/examples/Node2Node/Node2Node.ino deleted file mode 100644 index 5efd17a5..00000000 --- a/lib/MySensors/examples/Node2Node/Node2Node.ino +++ /dev/null @@ -1,76 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - tekka 2018 - * - * DESCRIPTION - * Node to node communication example, destination node id = ACTUATOR_ID - * Use SIGNING_ENABLED to enable soft/hard signing - * - */ -#define MY_DEBUG -#define MY_RADIO_RF24 -#define CHILD_SENSOR_ID 0 -#define ACTUATOR_ID 200 -//#define SIGNING_ENABLED // enable for secure actuator - -#if defined(SIGNING_ENABLED) -// Signing, select soft/hardware signing method -#define MY_SIGNING_SOFT -//#define MY_SIGNING_ATSHA204 -#define MY_DEBUG_VERBOSE_SIGNING -// Enable this if you want destination node to sign all messages sent to this node. -//#define MY_SIGNING_REQUEST_SIGNATURES -#endif - -// triggering interval -static const uint32_t trigger_ms = 10000; - -#include "MySensors.h" -MyMessage msgGeneral(CHILD_SENSOR_ID, V_STATUS); -uint32_t lastTrigger = 0; -bool actuatorStatus = false; - -void presentation(void) -{ - sendSketchInfo("Node2Node", __DATE__); - present(CHILD_SENSOR_ID, S_BINARY, "Remote"); -} - -void setup() -{ -#if defined(SIGNING_ENABLED) - SET_SIGN(ACTUATOR_ID); // define signing requirements for remote node -#endif -} - -void loop() -{ - if (millis() - lastTrigger > trigger_ms) { - lastTrigger = millis(); - // set destination address - msgGeneral.setDestination(ACTUATOR_ID); - // send message to node - send(msgGeneral.set(actuatorStatus)); - // invert status - actuatorStatus ^= true; - } -} diff --git a/lib/MySensors/examples/PHSensor/PHSensor.ino b/lib/MySensors/examples/PHSensor/PHSensor.ino deleted file mode 100644 index d6a51493..00000000 --- a/lib/MySensors/examples/PHSensor/PHSensor.ino +++ /dev/null @@ -1,85 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - mboyer85 - * - * DESCRIPTION - * Example sketch showing how to send PH readings back to the controller - */ - -// Enable debug prints to serial monitor -//#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define COMPARE_PH 1 // Send PH only if changed? 1 = Yes 0 = No - -uint32_t SLEEP_TIME = 60000; // Sleep time between reads (in milliseconds) -float lastPH; -bool receivedConfig = false; -bool metric = true; -// Initialize PH message -MyMessage msg(0, V_PH); - -void setup() -{ - //Setup your PH sensor here (I2C,Serial,Phidget...) -} - -float getPH() -{ - //query your PH sensor here (I2C,Serial,Phidget...) - float dummy = 7; - return dummy; -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("PH Sensor", "1.1"); - present(0, S_WATER_QUALITY); - -} - -void loop() -{ - float ph = getPH(); - -#if COMPARE_PH == 1 - if (lastPH != ph) { -#endif - - // Send in the new PH value - send(msg.set(ph, 1)); - // Save new PH value for next compare - lastPH = ph; - -#if COMPARE_PH == 1 - } -#endif - sleep(SLEEP_TIME); -} diff --git a/lib/MySensors/examples/PassiveNode/PassiveNode.ino b/lib/MySensors/examples/PassiveNode/PassiveNode.ino deleted file mode 100644 index 74d5bcc7..00000000 --- a/lib/MySensors/examples/PassiveNode/PassiveNode.ino +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - tekka - * - * DESCRIPTION - * Passive node example: This is a passive & independent reporting node - * - */ - -// Enable debug prints -#define MY_DEBUG - -// Enable passive mode -#define MY_PASSIVE_NODE - -// Passive mode requires static node ID -#define MY_NODE_ID 100 - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define CHILD_ID 0 // Id of the sensor child - -// Initialize general message -MyMessage msg(CHILD_ID, V_TEMP); - -void setup() -{ -} - -void presentation() -{ - // Send the sketch version information to the gateway and controller - sendSketchInfo("Passive node", "1.0"); - - // Register all sensors to gw (they will be created as child devices) - present(CHILD_ID, S_TEMP); -} - -void loop() -{ - // generate some random data - send(msg.set(25.0+random(0,30)/10.0,2)); - sleep(2000); -} diff --git a/lib/MySensors/examples/PingPongSensor/MYSLog.h b/lib/MySensors/examples/PingPongSensor/MYSLog.h deleted file mode 100644 index 25c20543..00000000 --- a/lib/MySensors/examples/PingPongSensor/MYSLog.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * Formatted logging to the Serial console. - * Compiled in by setting LOGDEBUG - * - * 2015-05-25 Bruce Lacey V1.0 - * - * Based upon Arduino Playground prior art and should be moved to - * the MySensors library at some point as a common debug logging facility - */ -#ifndef MYSLog_h -#define MYSLog_h - -#define LOGDEBUG 1 - -#if defined ( LOGDEBUG ) -#define LOG(fmt, args... ) debugLog( fmt, ## args ); -#else -#define LOG(fmt, args... ) -#endif - -void debugLog(const char *fmt, ... ) -{ - char buff[128]; - va_list args; - va_start (args, fmt); - vsnprintf(buff, sizeof(buff), fmt, args); - va_end (args); - buff[sizeof(buff)/sizeof(buff[0])-1]='\0'; - Serial.print(buff); -} - -void debugLog(const __FlashStringHelper *fmt, ... ) -{ - char buf[128]; // resulting string limited to 128 chars - va_list args; - va_start (args, fmt); -#ifdef __AVR__ - vsnprintf_P(buf, sizeof(buf), (const char *)fmt, args); // progmem for AVR -#else - vsnprintf(buf, sizeof(buf), (const char *)fmt, args); // for the rest of the world -#endif - va_end(args); - Serial.print(buf); -} - -#endif diff --git a/lib/MySensors/examples/PingPongSensor/PingPongSensor.ino b/lib/MySensors/examples/PingPongSensor/PingPongSensor.ino deleted file mode 100644 index 896df628..00000000 --- a/lib/MySensors/examples/PingPongSensor/PingPongSensor.ino +++ /dev/null @@ -1,127 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * This is a simple sketch used to demonstrate and test node-to-node MySensors communication. - * To use this sketch, assemble MySensors nodes - they need nothing more than a radio - * 1. Flash each node with the same sketch, open the console and type either 0 or 1 to the respective nodes to set their ID - * 2. You only need to set the node id once, and restart the nodes - * 3. To being a ping-pong test, simply type T in the console for one of the nodes. - * - * 2015-05-25 Bruce Lacey v1.0 - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include -#include "MYSLog.h" - -#define VSN "v1.0" - -// Define two generic nodes with a single child -#define YING 200 -#define YANG 201 -#define CHILD 1 - -MyMessage mPing(CHILD, V_VAR1); //Ping message -MyMessage mPong(CHILD, V_VAR2); //Pong message - -void setup() -{ -} - -void presentation() -{ - present(CHILD, S_CUSTOM); // - - sendSketchInfo( nodeTypeAsCharRepresentation( getNodeId() ), VSN ); - LOG(F("\n%sReady.\n"), nodeTypeAsCharRepresentation(getNodeId())); -} - -void loop() -{ - - // Interactive command and control - // Entering a number from 0 or 1 will write the node 200 (YING) or 201 (YANG) to EEPROM - // Entering T on either node will initiate a ping-pong test. - if (Serial.available()) { - byte inChar = Serial.read(); - uint8_t node = getNodeId(); - - // Manual Test Mode - if (inChar == 'T' || inChar == 't') { - LOG(F("T received - starting test...\n")); - MyMessage msg = mPong; - msg.sender = (node == YING ? YANG : YING); - sendPingOrPongResponse( msg ); - } else if (inChar == '0' or inChar == '1') { - byte nodeID = 200 + (inChar - '0'); - setNodeId(nodeID); - } else { - LOG("Invalid input\n"); - } - } -} - -void receive(const MyMessage &message) -{ - - LOG(F("Received %s from %s\n"), msgTypeAsCharRepresentation((mysensors_data_t)message.getType()), - nodeTypeAsCharRepresentation(message.sender)); - - delay(250); - sendPingOrPongResponse( message ); -} - -void sendPingOrPongResponse( MyMessage msg ) -{ - - MyMessage response = (msg.getType() == V_VAR1 ? mPong : mPing); - - LOG(F("Sending %s to %s\n"), msgTypeAsCharRepresentation( (mysensors_data_t)response.getType() ), - nodeTypeAsCharRepresentation(msg.sender)); - - // Set payload to current time in millis to ensure each message is unique - response.set( (uint32_t)millis() ); - response.setDestination(msg.sender); - send(response); -} - -void setNodeId(byte nodeID) -{ - LOG(F("Setting node id to: %i.\n***Please restart the node for changes to take effect.\n"), nodeID); - hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (byte)nodeID); -} - -const char * msgTypeAsCharRepresentation( mysensors_data_t mType ) -{ - return mType == V_VAR1 ? "Ping" : "Pong"; -} - -const char * nodeTypeAsCharRepresentation( uint8_t node ) -{ - return node == YING ? "Ying Node" : "Yang Node"; -} \ No newline at end of file diff --git a/lib/MySensors/examples/RFM69_RFM95_ATC_SignalReport/RFM69_RFM95_ATC_SignalReport.ino b/lib/MySensors/examples/RFM69_RFM95_ATC_SignalReport/RFM69_RFM95_ATC_SignalReport.ino deleted file mode 100644 index 34d18b65..00000000 --- a/lib/MySensors/examples/RFM69_RFM95_ATC_SignalReport/RFM69_RFM95_ATC_SignalReport.ino +++ /dev/null @@ -1,99 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - tekka - * - * DESCRIPTION - * ATC mode settings and signal report functions, on RFM69 and RFM95 nodes - * - */ - -// Enable debug prints -#define MY_DEBUG - -// Enable and select radio type attached - -// RFM69 -//#define MY_RADIO_RFM69 -//#define MY_RFM69_NEW_DRIVER // ATC on RFM69 works only with the new driver (not compatible with old=default driver) -//#define MY_RFM69_ATC_TARGET_RSSI_DBM (-70) // target RSSI -70dBm -//#define MY_RFM69_MAX_POWER_LEVEL_DBM (10) // max. TX power 10dBm = 10mW - -// RFM95 -#define MY_RADIO_RFM95 -#define MY_RFM95_ATC_TARGET_RSSI_DBM (-70) // target RSSI -70dBm -#define MY_RFM95_MAX_POWER_LEVEL_DBM (10) // max. TX power 10dBm = 10mW - -#include - -// ID of the sensor child -#define CHILD_ID_UPLINK_QUALITY (0) -#define CHILD_ID_TX_LEVEL (1) -#define CHILD_ID_TX_PERCENT (2) -#define CHILD_ID_TX_RSSI (3) -#define CHILD_ID_RX_RSSI (4) -#define CHILD_ID_TX_SNR (5) -#define CHILD_ID_RX_SNR (6) - - -// Initialize general message -MyMessage msgTxRSSI(CHILD_ID_TX_RSSI, V_CUSTOM); -MyMessage msgRxRSSI(CHILD_ID_RX_RSSI, V_CUSTOM); -MyMessage msgTxSNR(CHILD_ID_TX_SNR, V_CUSTOM); -MyMessage msgRxSNR(CHILD_ID_RX_SNR, V_CUSTOM); -MyMessage msgTxLevel(CHILD_ID_TX_LEVEL, V_CUSTOM); -MyMessage msgTxPercent(CHILD_ID_TX_PERCENT, V_CUSTOM); -MyMessage msgUplinkQuality(CHILD_ID_UPLINK_QUALITY, V_CUSTOM); - -void setup() -{ -} - - -void presentation() -{ - // Send the sketch version information to the gateway and controller - sendSketchInfo("ATC", "1.0"); - - // Register all sensors to gw (they will be created as child devices) - present(CHILD_ID_UPLINK_QUALITY, S_CUSTOM, "UPLINK QUALITY RSSI"); - present(CHILD_ID_TX_LEVEL, S_CUSTOM, "TX LEVEL DBM"); - present(CHILD_ID_TX_PERCENT, S_CUSTOM, "TX LEVEL PERCENT"); - present(CHILD_ID_TX_RSSI, S_CUSTOM, "TX RSSI"); - present(CHILD_ID_RX_RSSI, S_CUSTOM, "RX RSSI"); - present(CHILD_ID_TX_SNR, S_CUSTOM, "TX SNR"); - present(CHILD_ID_RX_SNR, S_CUSTOM, "RX SNR"); -} - -void loop() -{ - // send messages to GW - send(msgUplinkQuality.set(transportGetSignalReport(SR_UPLINK_QUALITY))); - send(msgTxLevel.set(transportGetSignalReport(SR_TX_POWER_LEVEL))); - send(msgTxPercent.set(transportGetSignalReport(SR_TX_POWER_PERCENT))); - // retrieve RSSI / SNR reports from incoming ACK - send(msgTxRSSI.set(transportGetSignalReport(SR_TX_RSSI))); - send(msgRxRSSI.set(transportGetSignalReport(SR_RX_RSSI))); - send(msgTxSNR.set(transportGetSignalReport(SR_TX_SNR))); - send(msgRxSNR.set(transportGetSignalReport(SR_RX_SNR))); - // wait a bit - wait(5000); -} diff --git a/lib/MySensors/examples/RelayActuator/RelayActuator.ino b/lib/MySensors/examples/RelayActuator/RelayActuator.ino deleted file mode 100644 index 998ee86b..00000000 --- a/lib/MySensors/examples/RelayActuator/RelayActuator.ino +++ /dev/null @@ -1,97 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * - * DESCRIPTION - * Example sketch showing how to control physical relays. - * This example will remember relay state after power failure. - * http://www.mysensors.org/build/relay - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -// Enable repeater functionality for this node -#define MY_REPEATER_FEATURE - -#include - -#define RELAY_PIN 4 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) -#define NUMBER_OF_RELAYS 1 // Total number of attached relays -#define RELAY_ON 1 // GPIO value to write to turn on attached relay -#define RELAY_OFF 0 // GPIO value to write to turn off attached relay - - -void before() -{ - for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { - // Then set relay pins in output mode - pinMode(pin, OUTPUT); - // Set relay to last known state (using eeprom storage) - digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); - } -} - -void setup() -{ - -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Relay", "1.0"); - - for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { - // Register all sensors to gw (they will be created as child devices) - present(sensor, S_BINARY); - } -} - - -void loop() -{ - -} - -void receive(const MyMessage &message) -{ - // We only expect one type of message from controller. But we better check anyway. - if (message.getType()==V_STATUS) { - // Change relay state - digitalWrite(message.getSensor()-1+RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF); - // Store state in eeprom - saveState(message.getSensor(), message.getBool()); - // Write some debug info - Serial.print("Incoming change for sensor:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(message.getBool()); - } -} - diff --git a/lib/MySensors/examples/RepeaterNode/RepeaterNode.ino b/lib/MySensors/examples/RepeaterNode/RepeaterNode.ino deleted file mode 100644 index 95a1abe5..00000000 --- a/lib/MySensors/examples/RepeaterNode/RepeaterNode.ino +++ /dev/null @@ -1,59 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * - * DESCRIPTION - * Example sketch showing how to create a node that repeats messages - * from nodes far from gateway back to gateway. - * It is important that nodes that has enabled repeater mode calls - * process() frequently. Repeaters should never sleep. - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -// Enabled repeater feature for this node -#define MY_REPEATER_FEATURE - -#include - -void setup() -{ - -} - -void presentation() -{ - //Send the sensor node sketch version information to the gateway - sendSketchInfo("Repeater Node", "1.0"); -} - -void loop() -{ -} - diff --git a/lib/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino b/lib/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino deleted file mode 100644 index 5a7e6054..00000000 --- a/lib/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino +++ /dev/null @@ -1,409 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * - * DESCRIPTION - * - * Secret Knock Sensor - * http://www.mysensors.org/build/knock - * - * See original instructions here (note: The MySensors adopted code might differ in wiring. The instructions below is correct): - * https://learn.adafruit.com/secret-knock-activated-drawer-lock/ - * Version 13.10.31 Built with Arduino IDE 1.0.5 - * - * By Steve Hoefer http://grathio.com - * Adapted to MySensors by Henrik Ekblad - * - * Licensed under Creative Commons Attribution-Noncommercial-Share Alike 3.0 - * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ - * (In short: Do what you want, as long as you credit me, don't relicense it, and don't sell it or use it in anything you sell without contacting me.) - * - * ------Wiring------ - * Pin 0: Program button used for recording a new Knock (connect Pin0 -> button -> GND) - * Pin 1: Optional: Connect LED here (remember resisor in series) - * Pin 2: Optional: Piezo element (for beeps). - * Pin 5: A sound sensor (digital output) for sensing knocks. See MySensors purchase guide. I used this: http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=200941260251&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg - * Pin 4: Connects to either 1. Relay which open door or lock or - * 2. transistor that opens a solenoid lock when HIGH (see adafruit guide for this option). - * - * - * Connect radio according as usual(you can skip IRQ pin) - * http://www.mysensors.org/build/connect_radio - */ - - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - - -#define CHILD_ID 99 // Id of the sensor child - -const byte eepromValid = 121; // If the first byte in eeprom is this then the data is valid. - -/*Pin definitions*/ -const int programButton = 0; // (Digital 0) Record A New Knock button. -const int ledPin = 1; // (Digital 1) The LED pin (if any) -const int knockSensor = - 5; // (Digital 5) for using the microphone digital output (tune knob to register knock) -const int audioOut = - 2; // (Digital 2) for using the peizo as an output device. (Thing that goes beep.) -const int lockPin = 4; // (Digital 4) The pin that activates the relay/solenoid lock. - -/*Tuning constants. Changing the values below changes the behavior of the device.*/ -int threshold = - 3; // Minimum signal from the piezo to register as a knock. Higher = less sensitive. Typical values 1 - 10 -const int rejectValue = - 25; // If an individual knock is off by this percentage of a knock we don't unlock. Typical values 10-30 -const int averageRejectValue = - 15; // If the average timing of all the knocks is off by this percent we don't unlock. Typical values 5-20 -const int knockFadeTime = - 150; // Milliseconds we allow a knock to fade before we listen for another one. (Debounce timer.) -const int lockOperateTime = - 2500; // Milliseconds that we operate the lock solenoid latch before releasing it. -const int maximumKnocks = 20; // Maximum number of knocks to listen for. -const int knockComplete = - 1200; // Longest time to wait for a knock before we assume that it's finished. (milliseconds) - -byte secretCode[maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Initial setup: "Shave and a Hair Cut, two bits." -int knockReadings[maximumKnocks]; // When someone knocks this array fills with the delays between knocks. -int knockSensorValue = 0; // Last reading of the knock sensor. -bool programModeActive = false; // True if we're trying to program a new knock. - -bool lockStatus; - -MyMessage lockMsg(CHILD_ID, V_LOCK_STATUS); - -void setup() -{ - - pinMode(ledPin, OUTPUT); - pinMode(knockSensor, INPUT); - pinMode(lockPin, OUTPUT); - pinMode(programButton, INPUT); - digitalWrite(programButton, HIGH); // Enable internal pull up - - readSecretKnock(); // Load the secret knock (if any) from EEPROM. - - digitalWrite(lockPin, - HIGH); // Unlock the door for a bit when we power up. For system check and to allow a way in if the key is forgotten - delay(500); // Wait a short time - - lockStatus = loadState(0); // Read last lock status from eeprom - setLockState(lockStatus, true); // Now set the last known state and send it to controller - - delay(500); // This delay is here because the solenoid lock returning to place can otherwise trigger and inadvertent knock. -} - -void presentation() -{ - sendSketchInfo("Secret Knock", "1.0"); - present(CHILD_ID, S_LOCK); -} - -void loop() -{ - // Listen for any knock at all. - knockSensorValue = digitalRead(knockSensor); - if (digitalRead(programButton) == LOW) { // is the program button pressed? - delay(100); // Cheap debounce. - if (digitalRead(programButton) == LOW) { - if (programModeActive == false) { // If we're not in programming mode, turn it on. - programModeActive = true; // Remember we're in programming mode. - digitalWrite(ledPin, HIGH); // Turn on the red light too so the user knows we're programming. - chirp(500, 1500); // And play a tone in case the user can't see the LED. - chirp(500, 1000); - } else { // If we are in programming mode, turn it off. - programModeActive = false; - digitalWrite(ledPin, LOW); - chirp(500, 1000); // Turn off the programming LED and play a sad note. - chirp(500, 1500); - delay(500); - } - while (digitalRead(programButton) == LOW) { - delay(10); // Hang around until the button is released. - } - } - delay(250); // Another cheap debounce. Longer because releasing the button can sometimes be sensed as a knock. - } - - - if (knockSensorValue == 0) { - if (programModeActive == true) { // Blink the LED when we sense a knock. - digitalWrite(ledPin, LOW); - } else { - digitalWrite(ledPin, HIGH); - } - knockDelay(); - if (programModeActive == true) { // Un-blink the LED. - digitalWrite(ledPin, HIGH); - } else { - digitalWrite(ledPin, LOW); - } - listenToSecretKnock(); // We have our first knock. Go and see what other knocks are in store... - } - -} - -// Records the timing of knocks. -void listenToSecretKnock() -{ - int i = 0; - // First reset the listening array. - for (i=0; i < maximumKnocks; i++) { - knockReadings[i] = 0; - } - - int currentKnockNumber = 0; // Position counter for the array. - uint32_t startTime = millis(); // Reference for when this knock started. - uint32_t now; - - do { // Listen for the next knock or wait for it to timeout. - knockSensorValue = digitalRead(knockSensor); - - if (knockSensorValue == 0) { // Here's another knock. Save the time between knocks. - Serial.println("knock"); - - now=millis(); - knockReadings[currentKnockNumber] = now - startTime; - currentKnockNumber ++; - startTime = now; - - if (programModeActive==true) { // Blink the LED when we sense a knock. - digitalWrite(ledPin, LOW); - } else { - digitalWrite(ledPin, HIGH); - } - knockDelay(); - if (programModeActive == true) { // Un-blink the LED. - digitalWrite(ledPin, HIGH); - } else { - digitalWrite(ledPin, LOW); - } - } - - now = millis(); - - // Stop listening if there are too many knocks or there is too much time between knocks. - } while ((now-startTime < knockComplete) && (currentKnockNumber < maximumKnocks)); - Serial.println("end"); - - //we've got our knock recorded, lets see if it's valid - if (programModeActive == false) { // Only do this if we're not recording a new knock. - if (validateKnock() == true) { - // Lock/unlock door - chirp(500, 1500); // And play a tone in case the user can't see the LED. - chirp(500, 1000); - setLockState(!lockStatus, true); - } else { - Serial.println("fail unlock"); - - // knock is invalid. Blink the LED as a warning to others. - for (i=0; i < 4; i++) { - digitalWrite(ledPin, HIGH); - delay(50); - digitalWrite(ledPin, LOW); - delay(50); - } - } - } else { // If we're in programming mode we still validate the lock because it makes some numbers we need, we just don't do anything with the return. - validateKnock(); - } -} - - -// Unlocks the door. -void setLockState(bool state, bool doSend) -{ - if (state) { - Serial.println("open lock"); - } else { - Serial.println("close lock"); - } - if (doSend) { - send(lockMsg.set(state)); - } - - digitalWrite(ledPin, state); - digitalWrite(lockPin, state); - saveState(0,state); - lockStatus = state; - delay(500); // This delay is here because releasing the latch can cause a vibration that will be sensed as a knock. -} - -// Checks to see if our knock matches the secret. -// Returns true if it's a good knock, false if it's not. -bool validateKnock() -{ - int i = 0; - - int currentKnockCount = 0; - int secretKnockCount = 0; - int maxKnockInterval = 0; // We use this later to normalize the times. - - for (i=0; i 0) { - currentKnockCount++; - } - if (secretCode[i] > 0) { - secretKnockCount++; - } - - if (knockReadings[i] > maxKnockInterval) { // Collect normalization data while we're looping. - maxKnockInterval = knockReadings[i]; - } - } - - // If we're recording a new knock, save the info and get out of here. - if (programModeActive == true) { - for (i=0; i < maximumKnocks; i++) { // Normalize the time between knocks. (the longest time = 100) - secretCode[i] = map(knockReadings[i], 0, maxKnockInterval, 0, 100); - } - saveSecretKnock(); // save the result to EEPROM - programModeActive = false; - playbackKnock(maxKnockInterval); - return false; - } - - if (currentKnockCount != - secretKnockCount) { // Easiest check first. If the number of knocks is wrong, don't unlock. - return false; - } - - /* Now we compare the relative intervals of our knocks, not the absolute time between them. - (ie: if you do the same pattern slow or fast it should still open the door.) - This makes it less picky, which while making it less secure can also make it - less of a pain to use if you're tempo is a little slow or fast. - */ - int totaltimeDifferences = 0; - for (int timeDiff = 0, i=0; i < maximumKnocks; i++) { // Normalize the times - knockReadings[i]= map(knockReadings[i], 0, maxKnockInterval, 0, 100); - timeDiff = abs(knockReadings[i] - secretCode[i]); - if (timeDiff > - rejectValue) { // Individual value too far out of whack. No access for this knock! - return false; - } - totaltimeDifferences += timeDiff; - } - // It can also fail if the whole thing is too inaccurate. - if (totaltimeDifferences / secretKnockCount > averageRejectValue) { - return false; - } - - return true; -} - - -// reads the secret knock from EEPROM. (if any.) -void readSecretKnock() -{ - byte reading; - reading = loadState(1); - if (reading == eepromValid) { // only read EEPROM if the signature byte is correct. - for (int i=0; i < maximumKnocks ; i++) { - secretCode[i] = loadState(i+2); - } - } -} - - -//saves a new pattern too eeprom -void saveSecretKnock() -{ - saveState(1, - 0); // clear out the signature. That way we know if we didn't finish the write successfully. - for (int i=0; i < maximumKnocks; i++) { - saveState(i+2, secretCode[i]); - } - saveState(1, eepromValid); // all good. Write the signature so we'll know it's all good. -} - -// Plays back the pattern of the knock in blinks and beeps -void playbackKnock(int maxKnockInterval) -{ - digitalWrite(ledPin, LOW); - delay(1000); - digitalWrite(ledPin, HIGH); - chirp(200, 1800); - for (int i = 0; i < maximumKnocks ; i++) { - digitalWrite(ledPin, LOW); - // only turn it on if there's a delay - if (secretCode[i] > 0) { - delay(map(secretCode[i], 0, 100, 0, - maxKnockInterval)); // Expand the time back out to what it was. Roughly. - digitalWrite(ledPin, HIGH); - chirp(200, 1800); - } - } - digitalWrite(ledPin, LOW); -} - -// Deals with the knock delay thingy. -void knockDelay() -{ - int itterations = (knockFadeTime / - 20); // Wait for the peak to dissipate before listening to next one. - for (int i=0; i < itterations; i++) { - delay(10); - analogRead( - knockSensor); // This is done in an attempt to defuse the analog sensor's capacitor that will give false readings on high impedance sensors. - delay(10); - } -} - -// Plays a non-musical tone on the piezo. -// playTime = milliseconds to play the tone -// delayTime = time in microseconds between ticks. (smaller=higher pitch tone.) -void chirp(int playTime, int delayTime) -{ - long loopTime = (playTime * 1000L) / delayTime; - pinMode(audioOut, OUTPUT); - for(int i=0; i < loopTime; i++) { - digitalWrite(audioOut, HIGH); - delayMicroseconds(delayTime); - digitalWrite(audioOut, LOW); - } - pinMode(audioOut, INPUT); -} - - - -void receive(const MyMessage &message) -{ - // We only expect one type of message from controller. But we better check anyway. - if (message.getType()==V_LOCK_STATUS) { - // Change relay state - setLockState(message.getBool(), false); - - // Write some debug info - Serial.print("Incoming lock status:"); - Serial.println(message.getBool()); - } -} - diff --git a/lib/MySensors/examples/SecureActuator/SecureActuator.ino b/lib/MySensors/examples/SecureActuator/SecureActuator.ino deleted file mode 100644 index c8ebf3ee..00000000 --- a/lib/MySensors/examples/SecureActuator/SecureActuator.ino +++ /dev/null @@ -1,128 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - */ -/** - * @ingroup MySigninggrp - * @{ - * @file SecureActuator.ino - * @brief Example sketch showing how to securely control locks. - * - * This example will remember lock state even after power failure. - * - * REVISION HISTORY - * - See git log (git log libraries/MySensors/examples/SecureActuator/SecureActuator.ino) - */ - -/** - * @example SecureActuator.ino - * This example implements a secure actuator in the form of a IO controlled electrical lock.
- * Multiple locks are supported as long as they are on subsequent IO pin indices. The first lock pin - * is defined by @ref LOCK_1. The number of locks is controlled by @ref NOF_LOCKS .
- * The sketch will require incoming messages to be signed and the use of signing backend is selected - * by @ref MY_SIGNING_ATSHA204 or @ref MY_SIGNING_SOFT. Hard or soft ATSHA204 signing is supported.
- * Whitelisting can be enabled through @ref MY_SIGNING_NODE_WHITELISTING in which case a single entry - * is provided in this example which typically should map to the gateway of the network. - */ - -#define MY_DEBUG //!< Enable debug prints to serial monitor -#define MY_DEBUG_VERBOSE_SIGNING //!< Enable signing related debug prints to serial monitor -#define MY_NODE_LOCK_FEATURE //!< Enable lockdown of node if suspicious activity is detected - -// Enable and select radio type attached -#define MY_RADIO_RF24 //!< nRF24L01 radio driver -//#define MY_RADIO_NRF5_ESB //!< nRF5 radio driver (RF24 compatible) -//#define MY_RADIO_RFM69 //!< RFM69 radio driver -//#define MY_RADIO_RFM95 //!< RFM95 radio driver - -// Select soft/hardware signing method -#define MY_SIGNING_SOFT //!< Software signing -//#define MY_SIGNING_ATSHA204 //!< Hardware signing using ATSHA204A - -// Enable node whitelisting -//#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} -// Enable this if you want destination node to sign all messages sent to this node. -#define MY_SIGNING_REQUEST_SIGNATURES //!< destination node signs all messages sent to this node - - -// SETTINGS FOR MY_SIGNING_SOFT -#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 //!< Unconnected analog pin for random seed - -// SETTINGS FOR MY_SIGNING_ATSHA204 -#ifndef MY_SIGNING_ATSHA204_PIN -#define MY_SIGNING_ATSHA204_PIN 17 //!< A3 - pin where ATSHA204 is attached -#endif - -#include - - -#define LOCK_1 3 //!< Arduino Digital I/O pin number for first lock (second on pin+1 etc) -#define NOF_LOCKS 1 //!< Total number of attached locks -#define LOCK_LOCK 1 //!< GPIO value to write to lock attached lock -#define LOCK_UNLOCK 0 //!< GPIO value to write to unlock attached lock - -void setup() -{ - for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS; lock++, pin++) { - // Set lock pins in output mode - pinMode(pin, OUTPUT); - // Set lock to last known state (using eeprom storage) - digitalWrite(pin, loadState(lock)?LOCK_LOCK:LOCK_UNLOCK); - } -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Secure Lock", "1.0"); - - // Fetch lock status - for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS; lock++, pin++) { - // Register all locks to gw (they will be created as child devices) - present(lock, S_LOCK, "SecureActuator", false); - } -} - -/** @brief Sketch execution code */ -void loop() -{ -} - -/** - * @brief Incoming message handler - * - * @param message The message to handle. - */ -void receive(const MyMessage &message) -{ - // We only expect one type of message from controller. But we better check anyway. - // And echoed messages are not accepted as control messages - if (message.getType()==V_LOCK_STATUS && message.getSensor()<=NOF_LOCKS && !message.isEcho()) { - // Change relay state - digitalWrite(message.getSensor()-1+LOCK_1, message.getBool()?LOCK_LOCK:LOCK_UNLOCK); - // Store state in eeprom - saveState(message.getSensor(), message.getBool()); - // Write some debug info - Serial.print("Incoming change for lock:"); - Serial.print(message.getSensor()); - Serial.print(", New status: "); - Serial.println(message.getBool()); - } -} -/** @}*/ diff --git a/lib/MySensors/examples/SecurityPersonalizer/SecurityPersonalizer.ino b/lib/MySensors/examples/SecurityPersonalizer/SecurityPersonalizer.ino deleted file mode 100644 index 999dd8af..00000000 --- a/lib/MySensors/examples/SecurityPersonalizer/SecurityPersonalizer.ino +++ /dev/null @@ -1,1872 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - */ -/** - * @ingroup MySigninggrp - * @{ - * @file SecurityPersonalizer.ino - * @brief Security personalization sketch - * - * REVISION HISTORY - * - See git log (git log libraries/MySensors/examples/SecurityPersonalizer/SecurityPersonalizer.ino) - */ - -/** - * @example SecurityPersonalizer.ino - * This sketch will personalize either none-volatile memory or ATSHA204A for security functions - * available in the MySensors library.
- * Details on personalization procedure is given in @ref personalization.
- * This sketch will when executed without modifications also print a guided workflow on the UART. - */ - -#include "sha204_library.h" -#include "sha204_lib_return_codes.h" -/** @brief Make use of the MySensors framework without invoking the entire system */ -#define MY_CORE_ONLY -#include - -/************************************ User defined key data ***************************************/ - -/** @brief The user-defined HMAC key to use unless @ref GENERATE_HMAC_KEY is set */ -#define MY_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 - -/** @brief The user-defined AES key to store in EEPROM unless @ref GENERATE_AES_KEY is set */ -#define MY_AES_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 - -/** @brief The user-defined soft serial to use for soft signing unless @ref GENERATE_SOFT_SERIAL is set */ -#define MY_SOFT_SERIAL 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF - -/***************************** Flags for guided personalization flow ******************************/ - -/** - * @def GENERATE_KEYS_ATSHA204A - * @brief Default settings for generating keys using ATSHA204A - * - * @note The generated keys displayed in the serial log with this setting needs to be written down - * and transferred to all nodes this gateway will communicate with. This is mandatory for ALL - * nodes for encryption (AES key). For signing (HMAC key) it is only required for nodes that - * use signing. Typically you set the values for @ref MY_HMAC_KEY and @ref MY_AES_KEY. - */ -//#define GENERATE_KEYS_ATSHA204A - -/** - * @def GENERATE_KEYS_SOFT - * @brief Default settings for generating keys using software - * - * @b Important
- * You will need to ensure @ref MY_SIGNING_SOFT_RANDOMSEED_PIN is set to an unconnected analog pin - * in order to provide entropy to the software RNG if your hardware has no HWRNG. - * - * @note The generated keys displayed in the serial log with this setting needs to be written down - * and transferred to all nodes this gateway will communicate with. This is mandatory for ALL - * nodes for encryption (AES key). For signing (HMAC key) it is only required for nodes that - * use signing. Typically you set the values for @ref MY_HMAC_KEY and @ref MY_AES_KEY. - */ -//#define GENERATE_KEYS_SOFT - -/** - * @def PERSONALIZE_ATSHA204A - * @brief Default settings for personalizing an ATSHA204A - * - * It is assumed that you have updated @ref MY_HMAC_KEY and @ref MY_AES_KEY with the keys displayed - * when executing this sketch with @ref GENERATE_KEYS_ATSHA204A or @ref GENERATE_KEYS_SOFT defined. - */ -//#define PERSONALIZE_ATSHA204A - -/** - * @def PERSONALIZE_SOFT - * @brief Default settings for personalizing EEPROM for software signing - * - * It is assumed that you have updated @ref MY_HMAC_KEY and @ref MY_AES_KEY with the keys displayed - * when executing this sketch with @ref GENERATE_KEYS_ATSHA204A or @ref GENERATE_KEYS_SOFT defined. - */ -//#define PERSONALIZE_SOFT - -/** - * @def PERSONALIZE_SOFT_RANDOM_SERIAL - * @brief This is an alternative to @ref PERSONALIZE_SOFT which will also store a randomly generated - * serial to EEPROM in addition to the actions performed by @ref PERSONALIZE_SOFT. Take note of the - * generated soft serial as it will be needed if you plan to use whitelisting. It should be - * unique for each node. - * - * @note This is only needed for targets that lack unique device IDs. The sketch will inform you if - * there is a need for generating a random serial or not. Check the "Hardware security - * peripherals" listing. If a target has a unique device ID and a serial in EEPROM, the serial - * in EEPROM will be used. If erased (replaced with FF:es) the unique device ID will be used - * instead. - */ -//#define PERSONALIZE_SOFT_RANDOM_SERIAL - -/*************************** The settings below are for advanced users ****************************/ -/** - * @def USE_SOFT_SIGNING - * @brief Uncomment this to generate keys by software and store them to EEPROM instead of ATSHA204A - */ -//#define USE_SOFT_SIGNING - -/** - * @def LOCK_ATSHA204A_CONFIGURATION - * @brief Uncomment this to enable locking the ATSHA204A configuration zone - * - * It is still possible to change the key, and this also enable random key generation. - * @warning BE AWARE THAT THIS PREVENTS ANY FUTURE CONFIGURATION CHANGE TO THE CHIP - */ -//#define LOCK_ATSHA204A_CONFIGURATION - -/** - * @def SKIP_UART_CONFIRMATION - * @brief Uncomment this for boards that lack UART - * - * This will disable additional confirmation for actions that are non-reversible. - * - * @b Important
For ATSHA204A, no confirmation will be required for locking any zones with this - * configuration! Also, if you generate keys on a board without UART, you have no way of determining - * what the key is unless it is stored in EEPROM. - */ -//#define SKIP_UART_CONFIRMATION - -/** - * @def GENERATE_HMAC_KEY - * @brief Uncomment this to generate a random HMAC key using ATSHA204A or software depending on - * @ref USE_SOFT_SIGNING - * @note If not enabled, key defined by @ref MY_HMAC_KEY will be used instead. - */ -//#define GENERATE_HMAC_KEY - -/** - * @def STORE_HMAC_KEY - * @brief Uncomment this to store HMAC key to ATSHA204A or EEPROM depending on @ref USE_SOFT_SIGNING - */ -//#define STORE_HMAC_KEY - -/** - * @def GENERATE_AES_KEY - * @brief Uncomment this to generate a random AES key using ATSHA204A or software depending on - * @ref USE_SOFT_SIGNING - * @note If not enabled, key defined by @ref MY_AES_KEY will be used instead. - */ -//#define GENERATE_AES_KEY - -/** - * @def STORE_AES_KEY - * @brief Uncomment this to store AES key to EEPROM - */ -//#define STORE_AES_KEY - -/** - * @def GENERATE_SOFT_SERIAL - * @brief Uncomment this to generate a random serial number for software signing - * @note If not enabled, serial defined by @ref MY_SOFT_SERIAL will be used instead. - */ -//#define GENERATE_SOFT_SERIAL - -/** - * @def STORE_SOFT_SERIAL - * @brief Uncomment this to store the serial number to EEPROM - */ -//#define STORE_SOFT_SERIAL - -/** - * @def PRINT_DETAILED_ATSHA204A_CONFIG - * @brief Uncomment to print the detailed ATSHA204A configuration - */ -//#define PRINT_DETAILED_ATSHA204A_CONFIG - -/** - * @def RESET_EEPROM_PERSONALIZATION - * @brief Uncomment to reset the personalization data in EEPROM to 0xFF:es - */ -//#define RESET_EEPROM_PERSONALIZATION - -/********************* Guided mode flag configurations (don't change these) ***********************/ -#ifdef GENERATE_KEYS_ATSHA204A -#define LOCK_ATSHA204A_CONFIGURATION // We have to lock configuration to enable random number generation -#define GENERATE_HMAC_KEY // Generate random HMAC key -#define GENERATE_AES_KEY // Generate random AES key -#define SKIP_UART_CONFIRMATION // This is an automated mode -#endif - -#ifdef GENERATE_KEYS_SOFT -#define USE_SOFT_SIGNING // Use software backend -#define GENERATE_HMAC_KEY // Generate random HMAC key -#define GENERATE_AES_KEY // Generate random AES key -#define SKIP_UART_CONFIRMATION // This is an automated mode -#endif - -#ifdef PERSONALIZE_ATSHA204A -#define LOCK_ATSHA204A_CONFIGURATION // We have to lock configuration to enable random number generation -#define STORE_HMAC_KEY // Store the HMAC key -#define STORE_AES_KEY // Store the AES key -#define SKIP_UART_CONFIRMATION // This is an automated mode -#endif - -#ifdef PERSONALIZE_SOFT_RANDOM_SERIAL -#define GENERATE_SOFT_SERIAL // Generate a soft serial number -#define PERSONALIZE_SOFT // Do the rest as PERSONALIZE_SOFT -#endif - -#ifdef PERSONALIZE_SOFT -#define USE_SOFT_SIGNING // Use software backend -#define STORE_HMAC_KEY // Store the HMAC key -#define STORE_AES_KEY // Store the AES key -#define STORE_SOFT_SERIAL // Store the soft serial number -#define SKIP_UART_CONFIRMATION // This is an automated mode -#endif - -#if defined(GENERATE_HMAC_KEY) || defined(GENERATE_AES_KEY) || defined(GENERATE_SOFT_SERIAL) -#define GENERATE_SOMETHING -#endif - -#if defined(MY_LOCK_MCU) -#undefine MY_LOCK_MCU // The Sketch after SecurityPersonaliter should lock the MCU -#endif - -/********************************** Preprocessor sanitychecks *************************************/ -#if defined(GENERATE_SOFT_SERIAL) && !defined(USE_SOFT_SIGNING) -#error Cannot generate soft serial using ATSHA204A, use USE_SOFT_SINGING for this -#endif -#if defined(STORE_SOFT_SERIAL) && !defined(USE_SOFT_SIGNING) -#error Cannot store soft serial to ATSHA204A, use USE_SOFT_SINGING for this -#endif -#if defined(PRINT_DETAILED_ATSHA204A_CONFIG) && defined(USE_SOFT_SIGNING) -#error Cannot print ATSHA204A config using software signing flag, disable USE_SOFT_SINGING for this -#endif -#if defined(LOCK_ATSHA204A_CONFIGURATION) && defined(USE_SOFT_SIGNING) -#error Cannot lock ATSHA204A config using software signing flag, disable USE_SOFT_SINGING for this -#endif -#ifdef GENERATE_KEYS_ATSHA204A -#ifdef USE_SOFT_SIGNING -#error You cannot select soft signing if you want to generate keys using ATSHA204A -#endif -#ifdef STORE_HMAC_KEY -#error Disable STORE_SOFT_KEY, you should not store keys in this mode -#endif -#ifdef STORE_SOFT_SERIAL -#error Disable STORE_SOFT_SERIAL, you should not store serial in this mode -#endif -#ifdef STORE_AES_KEY -#error Disable STORE_AES_KEY, you should not store keys in this mode -#endif -#if defined(GENERATE_KEYS_SOFT) ||\ - defined (PERSONALIZE_ATSHA204A) ||\ - defined (PERSONALIZE_SOFT) ||\ - defined (PERSONALIZE_SOFT_RANDOM_SERIAL) -#error You can not enable GENERATE_KEYS_ATSHA204A together with other guided modes -#endif -#endif // GENERATE_KEYS_ATSHA204A -#ifdef GENERATE_KEYS_SOFT -#ifdef STORE_HMAC_KEY -#error Disable STORE_SOFT_KEY, you should not store keys in this mode -#endif -#ifdef STORE_SOFT_SERIAL -#error Disable STORE_SOFT_SERIAL, you should not store serial in this mode -#endif -#ifdef STORE_AES_KEY -#error Disable STORE_AES_KEY, you should not store keys in this mode -#endif -#ifndef MY_SIGNING_SOFT_RANDOMSEED_PIN -#error You have to set MY_SIGNING_SOFT_RANDOMSEED_PIN to a suitable value in this mode -#endif -#if defined(GENERATE_KEYS_ATSHA204A) ||\ - defined (PERSONALIZE_ATSHA204A) ||\ - defined (PERSONALIZE_SOFT) ||\ - defined (PERSONALIZE_SOFT_RANDOM_SERIAL) -#error You can not enable GENERATE_KEYS_SOFT together with other guided modes -#endif -#endif // GENERATE_KEYS_SOFT -#ifdef PERSONALIZE_ATSHA204A -#ifdef USE_SOFT_SIGNING -#error You cannot select soft signing if you want to personalize an ATSHA204A -#endif -#if defined(GENERATE_KEYS_ATSHA204A) ||\ - defined (GENERATE_KEYS_SOFT) ||\ - defined (PERSONALIZE_SOFT) ||\ - defined (PERSONALIZE_SOFT_RANDOM_SERIAL) -#error You can not enable PERSONALIZE_ATSHA204A together with other guided modes -#endif -#ifdef RESET_EEPROM_PERSONALIZATION -#error You cannot reset EEPROM personalization when personalizing a device -#endif -#endif // PERSONALIZE_ATSHA204A -#ifdef PERSONALIZE_SOFT -#if defined(GENERATE_KEYS_ATSHA204A) ||\ - defined (GENERATE_KEYS_SOFT) ||\ - defined (PERSONALIZE_ATSHA204A) -#error You can not enable PERSONALIZE_SOFT together with other guided modes -#endif -#ifdef RESET_EEPROM_PERSONALIZATION -#error You cannot reset EEPROM personalization when personalizing a device -#endif -#endif // PERSONALIZE_SOFT -#ifdef PERSONALIZE_SOFT_RANDOM_SERIAL -#if defined(GENERATE_KEYS_SOFT) ||\ - defined (PERSONALIZE_ATSHA204A) ||\ - defined (GENERATE_KEYS_ATSHA204A) -#error You can only enable one of the guided modes at a time -#endif -#ifdef RESET_EEPROM_PERSONALIZATION -#error You cannot reset EEPROM personalization when personalizing a device -#endif -#endif // PERSONALIZE_SOFT_RANDOM_SERIAL - -#if !defined(GENERATE_KEYS_ATSHA204A) &&\ - !defined(GENERATE_KEYS_SOFT) &&\ - !defined(PERSONALIZE_ATSHA204A) &&\ - !defined(PERSONALIZE_SOFT) &&\ - !defined(PERSONALIZE_SOFT_RANDOM_SERIAL) &&\ - !defined(USE_SOFT_SIGNING) &&\ - !defined(LOCK_ATSHA204A_CONFIGURATION) &&\ - !defined(SKIP_UART_CONFIRMATION) &&\ - !defined(GENERATE_HMAC_KEY) &&\ - !defined(STORE_HMAC_KEY) &&\ - !defined(GENERATE_SOFT_SERIAL) &&\ - !defined(STORE_SOFT_SERIAL) &&\ - !defined(GENERATE_AES_KEY) &&\ - !defined(STORE_AES_KEY) &&\ - !defined(PRINT_DETAILED_ATSHA204A_CONFIG) &&\ - !defined(RESET_EEPROM_PERSONALIZATION) -/** @brief Set when there are no config flags defined */ -#define NO_SETTINGS_DEFINED -#endif - -#if defined(GENERATE_KEYS_ATSHA204A) ||\ - defined(GENERATE_KEYS_SOFT) ||\ - defined(PERSONALIZE_ATSHA204A) ||\ - defined(PERSONALIZE_SOFT) ||\ - defined(PERSONALIZE_SOFT_RANDOM_SERIAL) -/** @brief Set when there is a guided mode flag defined */ -#define GUIDED_MODE -#endif - -/************************************* Function declarations ***************************************/ -static void halt(bool success); -#ifdef GENERATE_SOMETHING -static bool generate_random_data(uint8_t* data, size_t sz); -#endif -static void generate_keys(void); -static void store_keys(void); -static void print_hex_buffer(uint8_t* data, size_t sz); -static void print_c_friendly_hex_buffer(uint8_t* data, size_t sz); -#ifdef STORE_HMAC_KEY -static bool store_hmac_key_data(uint8_t* data, size_t sz); -#endif -#ifdef STORE_AES_KEY -static bool store_aes_key_data(uint8_t* data, size_t sz); -#endif -#ifdef STORE_SOFT_SERIAL -static bool store_soft_serial_data(uint8_t* data, size_t sz); -#endif -#ifndef USE_SOFT_SIGNING -static void init_atsha204a_state(void); -#ifdef LOCK_ATSHA204A_CONFIGURATION -static void lock_atsha204a_config(void); -static uint16_t write_atsha204a_config_and_get_crc(void); -#endif -static bool get_atsha204a_serial(uint8_t* data); -#ifdef STORE_HMAC_KEY -static bool write_atsha204a_key(uint8_t* key); -#endif -#endif // not USE_SOFT_SIGNING -static void print_greeting(void); -static void print_ending(void); -static void probe_and_print_peripherals(void); -static void print_eeprom_data(void); -static void print_whitelisting_entry(void); -#ifdef PRINT_DETAILED_ATSHA204A_CONFIG -static void dump_detailed_atsha204a_configuration(void); -#endif -#ifdef RESET_EEPROM_PERSONALIZATION -static void reset_eeprom(void); -#endif -static void write_eeprom_checksum(void); - -/**************************************** File local data *****************************************/ -#if defined(GENERATE_HMAC_KEY) || defined(STORE_HMAC_KEY) -/** @brief The data to store as HAMC key in ATSHA204A or EEPROM */ -static uint8_t user_hmac_key[32] = {MY_HMAC_KEY}; -#endif - -#if defined(GENERATE_SOFT_SERIAL) || defined(STORE_SOFT_SERIAL) -/** @brief The data to store as soft serial in EEPROM */ -static uint8_t user_soft_serial[9] = {MY_SOFT_SERIAL}; -#endif - -#if defined(GENERATE_AES_KEY) || defined(STORE_AES_KEY) -/* @brief The data to store as AES key in EEPROM */ -static uint8_t user_aes_key[16] = {MY_AES_KEY}; -#endif - -#ifndef USE_SOFT_SIGNING -const int sha204Pin = MY_SIGNING_ATSHA204_PIN; //!< The IO pin to use for ATSHA204A -atsha204Class sha204(sha204Pin); //!< atsha204Class -static uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; -static uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; -static uint8_t ret_code; -static uint8_t lockConfig = 0; -static uint8_t lockValue = 0; -#endif -static bool has_device_unique_id = false; -static const uint8_t reset_buffer[32] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/******************************************* Functions ********************************************/ - -/** @brief Sketch setup code (all personalization is done here as it is a run-once sketch) */ -void setup() -{ - // Delay startup a bit for serial consoles to catch up - uint32_t enter = hwMillis(); - while (hwMillis() - enter < (uint32_t)500); -#ifdef USE_SOFT_SIGNING - // initialize pseudo-RNG - hwRandomNumberInit(); -#endif - - while(!Serial); // For USB enabled devices, wait for USB enumeration before continuing - - print_greeting(); - -#ifndef USE_SOFT_SIGNING - init_atsha204a_state(); - // Lock configuration now if requested to enable RNG in ATSHA -#ifdef LOCK_ATSHA204A_CONFIGURATION - lock_atsha204a_config(); -#endif -#endif - // Generate the requested keys (if any) - generate_keys(); - -#ifdef RESET_EEPROM_PERSONALIZATION - // If requested, reset EEPROM before storing keys - reset_eeprom(); -#endif - - // Store the keys (if configured to do so) - store_keys(); - - // Write a checksum on the EEPROM data - write_eeprom_checksum(); - - // Print current EEPROM - print_eeprom_data(); - print_whitelisting_entry(); - Serial.println(); - - print_ending(); - halt(true); -} - -/** @brief Sketch execution code (unused) */ -void loop() -{ -} - -/** @brief Print a notice and halt the execution */ -static void halt(bool success) -{ - Serial.println(); - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| Execution result |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); - if (success) { - Serial.println(F( - "| SUCCESS |")); - } else { - Serial.print(F( - "| FAILURE ")); -#ifdef USE_SOFT_SIGNING - Serial.println(F(" |")); -#else - if (ret_code != SHA204_SUCCESS) { - Serial.print(F("(last ATSHA204A return code: 0x")); - if (ret_code < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(ret_code, HEX); - Serial.println(F(") |")); - } else { - Serial.println(F(" |")); - } -#endif - } - Serial.println( - F("+------------------------------------------------------------------------------------+")); - while(1) { - doYield(); - } -} - -#ifdef GENERATE_SOMETHING -/** - * @brief Generate random data of specified size and store in provided buffer - * @param data Buffer to store bytes in (buffer is assumed to be of required size) - * @param sz Number of random bytes to generate - * @returns false if failed - */ -static bool generate_random_data(uint8_t* data, size_t sz) -{ -#if defined(USE_SOFT_SIGNING) && ! defined(MY_HW_HAS_GETENTROPY) - for (size_t i = 0; i < sz; i++) { - data[i] = random(256) ^ micros(); - uint32_t enter = hwMillis(); - while (hwMillis() - enter < (uint32_t)2); - } - return true; -#elif defined(USE_SOFT_SIGNING) && defined(MY_HW_HAS_GETENTROPY) - hwGetentropy(&data, sz); -#else - ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); - if ((ret_code != SHA204_SUCCESS) || (lockConfig != 0x00)) { - return false; - } else { - memcpy(data, rx_buffer+SHA204_BUFFER_POS_DATA, sz); - return true; - } -#endif // not USE_SOFT_SIGNING -} -#endif // GENERATE_SOMETHING - -/** @brief Generate keys depending on configuration */ -static void generate_keys(void) -{ -#ifdef GENERATE_SOMETHING - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| Key generation |")); - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); - Serial.println( - F("| Key ID | Status | Key |")); - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); -#endif -#ifdef GENERATE_HMAC_KEY - Serial.print(F("| HMAC | ")); - if (!generate_random_data(user_hmac_key, 32)) { - memset(user_hmac_key, 0xFF, 32); - Serial.print(F("FAILED | ")); - } else { - Serial.print(F("OK | ")); - } - print_hex_buffer(user_hmac_key, 32); - Serial.println(F(" |")); -#endif -#ifdef GENERATE_AES_KEY - Serial.print(F("| AES | ")); - if (!generate_random_data(user_aes_key, 16)) { - memset(user_aes_key, 0xFF, 16); - Serial.print(F("FAILED | ")); - } else { - Serial.print(F("OK | ")); - } - print_hex_buffer(user_aes_key, 16); - Serial.println(F(" |")); -#endif -#ifdef GENERATE_SOFT_SERIAL - Serial.print(F("| SERIAL | ")); - if (has_device_unique_id) { - Serial.println(F("N/A | MCU has a unique serial which will be used instead. |")); - } else { - if (!generate_random_data(user_soft_serial, 9)) { - memset(user_soft_serial, 0xFF, 9); - Serial.print(F("FAILED | ")); - } else { - Serial.print(F("OK | ")); - } - print_hex_buffer(user_soft_serial, 9); - Serial.println(F(" |")); - } -#endif -#if defined(GENERATE_SOMETHING) && !defined(PERSONALIZE_SOFT_RANDOM_SERIAL) - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); - Serial.println(); - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| Key copy section |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); -#ifdef GENERATE_HMAC_KEY - Serial.print(F("#define MY_HMAC_KEY ")); - print_c_friendly_hex_buffer(user_hmac_key, 32); - Serial.println(); -#endif -#ifdef GENERATE_AES_KEY - Serial.print(F("#define MY_AES_KEY ")); - print_c_friendly_hex_buffer(user_aes_key, 16); - Serial.println(); -#endif -#ifdef GENERATE_SOFT_SERIAL - Serial.print(F("#define MY_SOFT_SERIAL ")); - print_c_friendly_hex_buffer(user_soft_serial, 9); - Serial.println(); -#endif - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println(); -#elif defined(PERSONALIZE_SOFT_RANDOM_SERIAL) - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); - Serial.println(); -#endif -} - -#ifdef RESET_EEPROM_PERSONALIZATION -/** @brief Reset EEPROM */ -static void reset_eeprom(void) -{ - uint8_t validation_buffer[32]; - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| EEPROM reset |")); - Serial.println( - F("+--------+---------------------------------------------------------------------------+")); - Serial.println( - F("| Key ID | Status |")); - Serial.println( - F("+--------+---------------------------------------------------------------------------+")); - Serial.print(F("| HMAC | ")); - hwWriteConfigBlock((void*)reset_buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); - // Validate data written - hwReadConfigBlock((void*)validation_buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); - if (memcmp(validation_buffer, reset_buffer, 32) != 0) { - Serial.println(F("FAILED |")); - } else { - Serial.println(F("OK |")); - } - Serial.print(F("| AES | ")); - hwWriteConfigBlock((void*)reset_buffer, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); - // Validate data written - hwReadConfigBlock((void*)validation_buffer, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); - if (memcmp(validation_buffer, reset_buffer, 16) != 0) { - Serial.println(F("FAILED |")); - } else { - Serial.println(F("OK |")); - } - Serial.print(F("| SERIAL | ")); - hwWriteConfigBlock((void*)reset_buffer, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); - // Validate data written - hwReadConfigBlock((void*)validation_buffer, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); - if (memcmp(validation_buffer, reset_buffer, 9) != 0) { - Serial.println(F("FAILED |")); - } else { - Serial.println(F("OK |")); - } - Serial.println( - F("+--------+---------------------------------------------------------------------------+")); -} -#endif // RESET_EEPROM_PERSONALIZATION - -static void write_eeprom_checksum(void) -{ - uint8_t buffer[SIZE_SIGNING_SOFT_HMAC_KEY + SIZE_RF_ENCRYPTION_AES_KEY + SIZE_SIGNING_SOFT_SERIAL]; - uint8_t hash[32]; - uint8_t checksum; - hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, - SIZE_SIGNING_SOFT_HMAC_KEY); - hwReadConfigBlock((void*)&buffer[SIZE_SIGNING_SOFT_HMAC_KEY], - (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, SIZE_RF_ENCRYPTION_AES_KEY); - hwReadConfigBlock((void*)&buffer[SIZE_SIGNING_SOFT_HMAC_KEY + SIZE_RF_ENCRYPTION_AES_KEY], - (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, SIZE_SIGNING_SOFT_SERIAL); - hwReadConfigBlock((void*)&checksum, (void*)EEPROM_PERSONALIZATION_CHECKSUM_ADDRESS, - SIZE_PERSONALIZATION_CHECKSUM); - - SHA256(hash, buffer, sizeof(buffer)); - hwWriteConfigBlock((void*)&hash[0], (void*)EEPROM_PERSONALIZATION_CHECKSUM_ADDRESS, - SIZE_PERSONALIZATION_CHECKSUM); -} - -/** @brief Store keys depending on configuration */ -static void store_keys(void) -{ -#if defined(STORE_HMAC_KEY) || defined(STORE_AES_KEY) || defined(STORE_SOFT_SERIAL) - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| Key storage |")); - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); - Serial.println( - F("| Key ID | Status | Key |")); - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); -#endif -#ifdef STORE_HMAC_KEY - Serial.print(F("| HMAC | ")); - if (!store_hmac_key_data(user_hmac_key)) { - Serial.print(F("FAILED | ")); - } else { - Serial.print(F("OK | ")); - } - print_hex_buffer(user_hmac_key, 32); - Serial.println(F(" |")); -#endif -#ifdef STORE_AES_KEY - Serial.print(F("| AES | ")); - if (!store_aes_key_data(user_aes_key)) { - Serial.print(F("FAILED | ")); - } else { - Serial.print(F("OK | ")); - } - print_hex_buffer(user_aes_key, 16); - Serial.println(F(" |")); -#endif -#ifdef STORE_SOFT_SERIAL - Serial.print(F("| SERIAL | ")); - if (has_device_unique_id) { - memset(user_soft_serial, 0xFF, 9); - } - if (!store_soft_serial_data(user_soft_serial)) { - Serial.print(F("FAILED | ")); - } else { - Serial.print(F("OK | ")); - } - if (has_device_unique_id) { - Serial.println(F("EEPROM reset. MCU has a unique serial which will be used instead.|")); - } else { - print_hex_buffer(user_soft_serial, 9); - Serial.println(F(" |")); - } -#endif -#if defined(STORE_HMAC_KEY) || defined(STORE_AES_KEY) || defined(STORE_SOFT_SERIAL) - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); - Serial.println(); -#endif -} - -/** - * @brief Print provided buffer as HEX data on serial console - * @param data Buffer to print - * @param sz Number of bytes to print - */ -static void print_hex_buffer(uint8_t* data, size_t sz) -{ - for (size_t i=0; i> 2, 4, config_word, 0, NULL, 0, NULL, - WRITE_COUNT_SHORT, tx_buffer, WRITE_RSP_SIZE, rx_buffer); - if (ret_code != SHA204_SUCCESS) { - Serial.println( - F("+------------------------------------------------------------------------------------+")); - halt(false); - } - } - } - return crc; -} -#endif - -static bool get_atsha204a_serial(uint8_t* data) -{ - ret_code = sha204.getSerialNumber(rx_buffer); - if (ret_code != SHA204_SUCCESS) { - return false; - } else { - memcpy(data, rx_buffer, 9); - return true; - } -} - -#ifdef STORE_HMAC_KEY -/** - * @brief Write provided key to slot 0 - * @param key The key data to write - * @returns false if failed - */ -static bool write_atsha204a_key(uint8_t* key) -{ - // Write key to slot 0 - ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, - 0, SHA204_ZONE_ACCESS_32, key, 0, NULL, 0, NULL, - WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer); - if (ret_code != SHA204_SUCCESS) { - return false; - } else { - return true; - } -} -#endif // STORE_HMAC_KEY -#endif // not USE_SOFT_SIGNING - -/** @brief Print a greeting on serial console */ -static void print_greeting(void) -{ - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| MySensors security personalizer |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println(); -#ifdef NO_SETTINGS_DEFINED - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| You are running without any configuration flags set. |")); - Serial.println( - F("| No changes will be made to ATSHA204A or EEPROM except for the EEPROM checksum |")); - Serial.println( - F("| which will be updated. |")); - Serial.println( - F("| |")); - Serial.println( - F("| If you want to personalize your device, you have two options. |")); - Serial.println( - F("| |")); - Serial.println( - F("| 1. a. Enable either GENERATE_KEYS_ATSHA204A or GENERATE_KEYS_SOFT |")); - Serial.println( - F("| This will generate keys for ATSHA204A or software signing. |")); - Serial.println( - F("| b. Execute the sketch. You will be guided through the steps below under |")); - Serial.println( - F("| WHAT TO DO NEXT? |")); - Serial.println( - F("| c. Copy the generated keys and replace the topmost definitions in this file. |")); - Serial.println( - F("| d. Save the sketch and then disable the flag you just enabled. |")); - Serial.println( - F("| e. Enable PERSONALIZE_ATSHA204A to personalize the ATSHA204A device. |")); - Serial.println( - F("| or |")); - Serial.println( - F("| Enable PERSONALIZE_SOFT to personalize the EEPROM for software signing. |")); - Serial.println( - F("| If you want to use whitelisting you need to pick a unique serial number |")); - Serial.println( - F("| for each device you run the sketch on and fill in MY_SOFT_SERIAL. |")); - Serial.println( - F("| or |")); - Serial.println( - F("| Enable PERSONALIZE_SOFT_RANDOM_SERIAL to personalzie the EEPROM and |")); - Serial.println( - F("| include a new random serial number every time the sketch is executed. |")); - Serial.println( - F("| Take note of each saved serial number if you plan to use whitelisting. |")); - Serial.println( - F("| f. Execute the sketch on each device you want to personalize that is supposed |")); - Serial.println( - F("| to communicate securely. |")); - Serial.println( - F("| |")); - Serial.println( - F("| 2. Enable any configuration flag as you see fit. |")); - Serial.println( - F("| It is assumed that you know what you are doing. |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println(); -#else - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| Configuration settings |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); -#if defined(GENERATE_KEYS_ATSHA204A) - Serial.println( - F("| * Guided key generation for ATSHA204A using ATSHA024A |")); -#endif -#if defined(GENERATE_KEYS_SOFT) - Serial.println( - F("| * Guided key generation for EEPROM using software |")); -#endif -#if defined(PERSONALIZE_ATSHA204A) - Serial.println( - F("| * Guided personalization/storage of keys in ATSHA204A |")); -#endif -#if defined(PERSONALIZE_SOFT) - Serial.println( - F("| * Guided personalization/storage of keys in EEPROM |")); -#endif -#if defined(PERSONALIZE_SOFT_RANDOM_SERIAL) - Serial.println( - F("| * Guided storage and generation of random serial in EEPROM |")); -#endif -#if defined(USE_SOFT_SIGNING) - Serial.println( - F("| * Software based personalization (no ATSHA204A usage whatsoever) |")); -#else - Serial.println( - F("| * ATSHA204A based personalization |")); -#endif -#if defined(LOCK_ATSHA204A_CONFIGURATION) - Serial.println( - F("| * Will lock ATSHA204A configuration |")); -#endif -#if defined(SKIP_UART_CONFIRMATION) - Serial.println( - F("| * Will not require any UART confirmations |")); -#endif -#if defined(GENERATE_HMAC_KEY) - Serial.print( - F("| * Will generate HMAC key using ")); -#if defined(USE_SOFT_SIGNING) - Serial.println( - F("software |")); -#else - Serial.println( - F("ATSHA204A |")); -#endif -#endif -#if defined(STORE_HMAC_KEY) - Serial.print(F("| * Will store HMAC key to ")); -#if defined(USE_SOFT_SIGNING) - Serial.println( - F("EEPROM |")); -#else - Serial.println( - F("ATSHA204A |")); -#endif -#endif -#if defined(GENERATE_AES_KEY) - Serial.print( - F("| * Will generate AES key using ")); -#if defined(USE_SOFT_SIGNING) - Serial.println( - F("software |")); -#else - Serial.println( - F("ATSHA204A |")); -#endif -#endif -#if defined(STORE_AES_KEY) - Serial.println( - F("| * Will store AES key to EEPROM |")); -#endif -#if defined(GENERATE_SOFT_SERIAL) - Serial.println( - F("| * Will generate soft serial using software |")); -#endif -#if defined(STORE_SOFT_SERIAL) - Serial.println( - F("| * Will store soft serial to EEPROM |")); -#endif -#if defined(PRINT_DETAILED_ATSHA204A_CONFIG) - Serial.println( - F("| * Will print detailed ATSHA204A configuration |")); -#endif -#if defined(RESET_EEPROM_PERSONALIZATION) - Serial.println( - F("| * Will reset EEPROM personalization data |")); -#endif - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println(); -#endif // not NO_SETTINGS_DEFINED - probe_and_print_peripherals(); -} - -static void print_ending(void) -{ -#if defined(GUIDED_MODE) || defined(NO_SETTINGS_DEFINED) - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| WHAT TO DO NEXT? |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); -#ifdef NO_SETTINGS_DEFINED - Serial.println( - F("| To proceed with the personalization, enable GENERATE_KEYS_ATSHA204A or |")); - Serial.println( - F("| GENERATE_KEYS_SOFT depending on what type of signing backend you plan to use. |")); - Serial.println( - F("| Both options will generate an AES key for encryption if you plan to use that. |")); - Serial.println( - F("| Recompile, upload and run the sketch again for further instructions. |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); -#endif -#ifdef GENERATE_KEYS_ATSHA204A - Serial.println( - F("| To proceed with the personalization, copy the keys shown in the Key copy section, |")); - Serial.println( - F("| and replace the corresponding definitions in the top of the sketch, then disable |")); - Serial.println( - F("| GENERATE_KEYS_ATSHA204A and enable PERSONALIZE_ATSHA204A. |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); -#endif -#ifdef GENERATE_KEYS_SOFT - Serial.println( - F("| To proceed with the personalization, copy the keys shown in the Key copy section, |")); - Serial.println( - F("| and replace the corresponding definitions in the top of the sketch, then disable |")); - Serial.println( - F("| GENERATE_KEYS_SOFT and enable PERSONALIZE_SOFT or PERSONALIZE_SOFT_RANDOM_SERIAL. |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); -#endif -#if defined(PERSONALIZE_ATSHA204A) ||\ - defined(PERSONALIZE_SOFT) ||\ - defined(PERSONALIZE_SOFT_RANDOM_SERIAL) - Serial.println( - F("| This device has now been personalized. Run this sketch with its current settings |")); - Serial.println( - F("| on all the devices in your network that have security enabled. |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); -#endif -#endif // GUIDED_MODE or NO_SETTINGS_DEFINED -} - -static void probe_and_print_peripherals(void) -{ - unique_id_t uniqueID; - - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| Hardware security peripherals |")); - Serial.println( - F("+--------------+--------------+--------------+------------------------------+--------+")); - Serial.println( - F("| Device | Status | Revision | Serial number | Locked |")); - Serial.println( - F("+--------------+--------------+--------------+------------------------------+--------+")); -#if defined(ARDUINO_ARCH_AVR) - Serial.print(F("| AVR | DETECTED | N/A | ")); -#elif defined(ARDUINO_ARCH_ESP8266) - Serial.print(F("| ESP8266 | DETECTED | N/A | ")); -#elif defined(ARDUINO_ARCH_SAMD) - Serial.print(F("| SAMD | DETECTED | N/A | ")); -#elif defined(ARDUINO_ARCH_STM32F1) - Serial.print(F("| STM32F1 | DETECTED | N/A | ")); -#elif defined(__linux__) - Serial.print(F("| Linux | DETECTED | N/A | ")); -#else - Serial.print(F("| Unknown | DETECTED | N/A | ")); -#endif - if (hwUniqueID(&uniqueID)) { - has_device_unique_id = true; - print_hex_buffer(uniqueID, 9); - Serial.println(F(" | N/A |")); - } else { - Serial.println(F("N/A (generation required) | N/A |")); - } - Serial.println( - F("+--------------+--------------+--------------+------------------------------+--------+")); -#ifndef USE_SOFT_SIGNING - Serial.print(F("| ATSHA204A | ")); - ret_code = sha204.sha204c_wakeup(rx_buffer); - if (ret_code != SHA204_SUCCESS) { - ret_code = SHA204_SUCCESS; // Reset retcode to avoid false negative execution result - Serial.println(F("NOT DETECTED | N/A | N/A | N/A |")); - } else { - uint8_t buffer[9]; - Serial.print(F("DETECTED | ")); - ret_code = sha204.sha204m_dev_rev(tx_buffer, rx_buffer); - if (ret_code != SHA204_SUCCESS) { - Serial.print(F("FAILED | ")); - } else { - print_hex_buffer(&rx_buffer[SHA204_BUFFER_POS_DATA], 4); - Serial.print(F(" | ")); - } - if (!get_atsha204a_serial(buffer)) { - memset(buffer, 0xFF, 9); - Serial.print(F("FAILED | ")); - } else { - print_hex_buffer(buffer, 9); - Serial.print(F(" | ")); - } - ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); - if (ret_code != SHA204_SUCCESS) { - Serial.println("FAILED |"); - } else { - if (rx_buffer[SHA204_BUFFER_POS_DATA+3] == 0x00) { - Serial.println("YES |"); - } else { - Serial.println("NO |"); - } - } - } - Serial.println( - F("+--------------+--------------+--------------+------------------------------+--------+")); -#ifdef PRINT_DETAILED_ATSHA204A_CONFIG - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| Current ATSHA204A Configuration |")); - dump_detailed_atsha204a_configuration(); -#endif -#endif // not USE_SOFT_SIGNING - Serial.println(); -} - -static void print_eeprom_data(void) -{ - uint8_t buffer[32]; - - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| EEPROM |")); - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); - Serial.println( - F("| Key ID | Status | Key |")); - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); - Serial.print(F("| HMAC | ")); - hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); - if (!memcmp(buffer, reset_buffer, 32)) { - Serial.print(F("RESET | ")); - } else { - Serial.print(F("OK | ")); - } - print_hex_buffer(buffer, 32); - Serial.println(F(" |")); - Serial.print(F("| AES | ")); - hwReadConfigBlock((void*)buffer, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); - if (!memcmp(buffer, reset_buffer, 16)) { - Serial.print(F("RESET | ")); - } else { - Serial.print(F("OK | ")); - } - print_hex_buffer(buffer, 16); - Serial.println(F(" |")); - Serial.print(F("| SERIAL | ")); - hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); - if (!memcmp(buffer, reset_buffer, 9)) { - if (has_device_unique_id) { - Serial.println(F("N/A | Device unique serial, not stored in EEPROM |")); - } else { - Serial.print(F("RESET | ")); - print_hex_buffer(buffer, 9); - Serial.println(F(" |")); - } - } else { - Serial.print(F("OK | ")); - print_hex_buffer(buffer, 9); - Serial.println(F(" |")); - } - Serial.println( - F("+--------+--------+------------------------------------------------------------------+")); - Serial.println(); -} - -static void print_whitelisting_entry(void) -{ - uint8_t buffer[9]; -#ifdef USE_SOFT_SIGNING - unique_id_t uniqueID; - hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); - if (!memcmp(buffer, reset_buffer, 9)) { - // Serial reset in EEPROM, check for unique ID - if (hwUniqueID(&uniqueID)) { - memcpy(buffer, uniqueID, 9); - } - } -#else - // If ATSHA204A is used, use that serial here - if (!get_atsha204a_serial(buffer)) { - memset(buffer, 0xFF, 9); - } -#endif - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.println( - F("| This nodes whitelist entry on other nodes |")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); - Serial.print(F("{.nodeId = ,.serial = {")); - print_c_friendly_hex_buffer(buffer, 9); - Serial.println(F("}}")); - Serial.println( - F("+------------------------------------------------------------------------------------+")); -} - -#ifdef PRINT_DETAILED_ATSHA204A_CONFIG -/** @brief Dump current configuration to UART */ -static void dump_detailed_atsha204a_configuration(void) -{ - Serial.println( - F("+---------------------------------------------------------------++-------------------+")); - Serial.println( - F("| Fieldname || Data |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - for (int i=0; i < 88; i += 4) { - ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i); - if (ret_code != SHA204_SUCCESS) { - Serial.println( - F("+------------------------------------------------------------------------------------+")); - halt(false); - } - if (i == 0x00) { - Serial.print(F("| SN[0:1] | SN[2:3] || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - } else if (i == 0x04) { - Serial.print(F("| Revnum || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+---------------------------------------------------------------++-------------------+")); - } else if (i == 0x08) { - Serial.print(F("| SN[4:7] || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x0C) { - Serial.print(F("| SN[8] | Reserved13 | I2CEnable | Reserved15 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" | ")); - } else { - Serial.println(F(" |")); - } - } - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x10) { - Serial.print(F("| I2CAddress | TempOffset | OTPmode | SelectorMode || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" | ")); - } else { - Serial.println(F(" |")); - } - } - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x14) { - Serial.print(F("| SlotConfig00 | SlotConfig01 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - } else if (i == 0x18) { - Serial.print(F("| SlotConfig02 | SlotConfig03 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - } else if (i == 0x1C) { - Serial.print(F("| SlotConfig04 | SlotConfig05 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - } else if (i == 0x20) { - Serial.print(F("| SlotConfig06 | SlotConfig07 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - } else if (i == 0x24) { - Serial.print(F("| SlotConfig08 | SlotConfig09 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - } else if (i == 0x28) { - Serial.print(F("| SlotConfig0A | SlotConfig0B || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - } else if (i == 0x2C) { - Serial.print(F("| SlotConfig0C | SlotConfig0D || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+-------------------------------+-------------------------------++---------+---------+")); - } else if (i == 0x30) { - Serial.print(F("| SlotConfig0E | SlotConfig0F || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) { - Serial.print(F(" | ")); - } else if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x34) { - Serial.print(F("| UseFlag00 | UpdateCount00 | UseFlag01 | UpdateCount01 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" | ")); - } else { - Serial.println(F(" |")); - } - } - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x38) { - Serial.print(F("| UseFlag02 | UpdateCount02 | UseFlag03 | UpdateCount03 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" | ")); - } else { - Serial.println(F(" |")); - } - } - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x3C) { - Serial.print(F("| UseFlag04 | UpdateCount04 | UseFlag05 | UpdateCount05 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" | ")); - } else { - Serial.println(F(" |")); - } - } - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x40) { - Serial.print(F("| UseFlag06 | UpdateCount06 | UseFlag07 | UpdateCount07 || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" | ")); - } else { - Serial.println(F(" |")); - } - } - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x44) { - Serial.print(F("| LastKeyUse[0:3] || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+---------------------------------------------------------------++-------------------+")); - } else if (i == 0x48) { - Serial.print(F("| LastKeyUse[4:7] || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+---------------------------------------------------------------++-------------------+")); - } else if (i == 0x4C) { - Serial.print(F("| LastKeyUse[8:B] || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+---------------------------------------------------------------++-------------------+")); - } else if (i == 0x50) { - Serial.print(F("| LastKeyUse[C:F] || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" ")); - } - } - Serial.println(F(" |")); - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } else if (i == 0x54) { - Serial.print(F("| UserExtra | Selector | LockValue | LockConfig || ")); - for (int j=0; j<4; j++) { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) { - Serial.print(F(" | ")); - } else { - Serial.println(F(" |")); - } - } - Serial.println( - F("+---------------+---------------+---------------+---------------++----+----+----+----+")); - } - } -} -#endif // PRINT_DETAILED_ATSHA204A_CONFIG - -// Doxygen specific constructs, not included when built normally -// This is used to enable disabled macros/definitions to be included in the documentation as well. -#if DOXYGEN -#define GENERATE_KEYS_ATSHA204A -#define GENERATE_KEYS_SOFT -#define PERSONALIZE_ATSHA204A -#define PERSONALIZE_SOFT -#define PERSONALIZE_SOFT_RANDOM_SERIAL -#define USE_SOFT_SIGNING -#define LOCK_ATSHA204A_CONFIGURATION -#define SKIP_UART_CONFIRMATION -#define GENERATE_HMAC_KEY -#define STORE_HMAC_KEY -#define GENERATE_AES_KEY -#define STORE_AES_KEY -#define GENERATE_SOFT_SERIAL -#define STORE_SOFT_SERIAL -#define PRINT_DETAILED_ATSHA204A_CONFIG -#define RESET_EEPROM_PERSONALIZATION -#endif - -/** @}*/ \ No newline at end of file diff --git a/lib/MySensors/examples/SecurityPersonalizer/sha204_lib_return_codes.h b/lib/MySensors/examples/SecurityPersonalizer/sha204_lib_return_codes.h deleted file mode 100644 index 0aaefaaa..00000000 --- a/lib/MySensors/examples/SecurityPersonalizer/sha204_lib_return_codes.h +++ /dev/null @@ -1,45 +0,0 @@ -// ---------------------------------------------------------------------------- -// ATMEL Microcontroller Software Support - Colorado Springs, CO - -// ---------------------------------------------------------------------------- -// DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR -// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE -// DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// ---------------------------------------------------------------------------- - -/** \file - * \brief SHA204 Library Return Code Definitions - * \author Atmel Crypto Products - * \date September 27, 2010 - */ - -#ifndef SHA204_LIB_RETURN_CODES_H -# define SHA204_LIB_RETURN_CODES_H - -#include // data type definitions - -#define SHA204_SUCCESS ((uint8_t) 0x00) //!< Function succeeded. -#define SHA204_PARSE_ERROR ((uint8_t) 0xD2) //!< response status byte indicates parsing error -#define SHA204_CMD_FAIL ((uint8_t) 0xD3) //!< response status byte indicates command execution error -#define SHA204_STATUS_CRC ((uint8_t) 0xD4) //!< response status byte indicates CRC error -#define SHA204_STATUS_UNKNOWN ((uint8_t) 0xD5) //!< response status byte is unknown -#define SHA204_FUNC_FAIL ((uint8_t) 0xE0) //!< Function could not execute due to incorrect condition / state. -#define SHA204_GEN_FAIL ((uint8_t) 0xE1) //!< unspecified error -#define SHA204_BAD_PARAM ((uint8_t) 0xE2) //!< bad argument (out of range, null pointer, etc.) -#define SHA204_INVALID_ID ((uint8_t) 0xE3) //!< invalid device id, id not set -#define SHA204_INVALID_SIZE ((uint8_t) 0xE4) //!< Count value is out of range or greater than buffer size. -#define SHA204_BAD_CRC ((uint8_t) 0xE5) //!< incorrect CRC received -#define SHA204_RX_FAIL ((uint8_t) 0xE6) //!< Timed out while waiting for response. Number of bytes received is > 0. -#define SHA204_RX_NO_RESPONSE ((uint8_t) 0xE7) //!< Not an error while the Command layer is polling for a command response. -#define SHA204_RESYNC_WITH_WAKEUP ((uint8_t) 0xE8) //!< re-synchronization succeeded, but only after generating a Wake-up - -#define SHA204_COMM_FAIL ((uint8_t) 0xF0) //!< Communication with device failed. Same as in hardware dependent modules. -#define SHA204_TIMEOUT ((uint8_t) 0xF1) //!< Timed out while waiting for response. Number of bytes received is 0. - -#endif diff --git a/lib/MySensors/examples/SecurityPersonalizer/sha204_library.cpp b/lib/MySensors/examples/SecurityPersonalizer/sha204_library.cpp deleted file mode 100644 index d21eb51a..00000000 --- a/lib/MySensors/examples/SecurityPersonalizer/sha204_library.cpp +++ /dev/null @@ -1,861 +0,0 @@ -#include "Arduino.h" -#include "sha204_library.h" -#include "sha204_lib_return_codes.h" - - -// atsha204Class Constructor -// Feed this function the Arduino-ized pin number you want to assign to the ATSHA204's SDA pin -// For AVR ARCH, this will find the DDRX, PORTX, and PINX registrs it'll need to point to to control that pin -// As well as the bit value for each of those registers -// For others it will only store the pin number which is used in subsequent functions - -atsha204Class::atsha204Class(uint8_t pin) -{ -#if defined(ARDUINO_ARCH_AVR) - device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin - uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers - - // Point to data direction register port of pin - device_port_DDR = portModeRegister(port); - // Point to output register of pin - device_port_OUT = portOutputRegister(port); - // Point to input register of pin - device_port_IN = portInputRegister(port); -#else - device_pin = pin; -#endif -} - -/* Puts a the ATSHA204's unique, 4-byte serial number in the response array - returns an SHA204 Return code */ -uint8_t atsha204Class::getSerialNumber(uint8_t * response) -{ - uint8_t readCommand[READ_COUNT]; - uint8_t readResponse[READ_4_RSP_SIZE]; - - /* read from bytes 0->3 of config zone */ - uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03); - if (!returnCode) { // should return 0 if successful - for (int i=0; i<4; i++) { // store bytes 0-3 into respones array - response[i] = readResponse[SHA204_BUFFER_POS_DATA+i]; - } - - /* read from bytes 8->11 of config zone */ - returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN47); - - for (int i=4; i<8; i++) { // store bytes 4-7 of SN into response array - response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)]; - } - - if (!returnCode) { - /* Finally if last two reads were successful, read byte 8 of the SN */ - returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8); - response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE - } - } - - return returnCode; -} - -/* Calculates CRC16 value of provided data (and optionally including provided existing CRC16 data) - returns the calculated CRC16 value */ -uint16_t atsha204Class::calculateAndUpdateCrc(uint8_t length, uint8_t *data, uint16_t current_crc) -{ - uint8_t counter; - uint16_t crc_register = current_crc; - uint16_t polynom = 0x8005; - uint8_t shift_register; - uint8_t data_bit, crc_bit; - - for (counter = 0; counter < length; counter++) { - for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { - data_bit = (data[counter] & shift_register) ? 1 : 0; - crc_bit = crc_register >> 15; - - // Shift CRC to the left by 1. - crc_register <<= 1; - - if ((data_bit ^ crc_bit) != 0) { - crc_register ^= polynom; - } - } - } - return crc_register; -} - -/* SWI bit bang functions */ - -void atsha204Class::swi_set_signal_pin(uint8_t is_high) -{ - SHA204_SET_OUTPUT(); - if (is_high) { - SHA204_POUT_HIGH(); - } else { - SHA204_POUT_LOW(); - } - -} - -uint8_t atsha204Class::swi_send_bytes(uint8_t count, uint8_t *buffer) -{ - uint8_t i, bit_mask; - - // Disable interrupts while sending. - noInterrupts(); //swi_disable_interrupts(); - - // Set signal pin as output. - SHA204_POUT_HIGH(); - SHA204_SET_OUTPUT(); - // Wait turn around time. - delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; - - for (i = 0; i < count; i++) { - for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { - if (bit_mask & buffer[i]) { - SHA204_POUT_LOW(); - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); - delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; - } else { - // Send a zero bit. - SHA204_POUT_LOW(); - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_LOW(); - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); - delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5; - } - } - } - interrupts(); //swi_enable_interrupts(); - return SWI_FUNCTION_RETCODE_SUCCESS; -} - -uint8_t atsha204Class::swi_send_byte(uint8_t value) -{ - return swi_send_bytes(1, &value); -} - -uint8_t atsha204Class::swi_receive_bytes(uint8_t count, uint8_t *buffer) -{ - uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS; - uint8_t i; - uint8_t bit_mask; - uint8_t pulse_count; - uint8_t timeout_count; - - // Disable interrupts while receiving. - noInterrupts(); //swi_disable_interrupts(); - - // Configure signal pin as input - SHA204_SET_INPUT(); - - // Receive bits and store in buffer. - for (i = 0; i < count; i++) { - for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { - pulse_count = 0; - - // Make sure that the variable below is big enough. - // Change it to uint16_t if 255 is too small, but be aware that - // the loop resolution decreases on an 8-bit controller in that case. - timeout_count = START_PULSE_TIME_OUT; - - // Detect start bit. - while (--timeout_count > 0) { - // Wait for falling edge. - if (SHA204_PIN_READ() == 0) { - break; - } - } - - if (timeout_count == 0) { - status = SWI_FUNCTION_RETCODE_TIMEOUT; - break; - } - - do { - // Wait for rising edge. - if (SHA204_PIN_READ() != 0) { - // For an Atmel microcontroller this might be faster than "pulse_count++". - pulse_count = 1; - break; - } - } while (--timeout_count > 0); - - if (pulse_count == 0) { - status = SWI_FUNCTION_RETCODE_TIMEOUT; - break; - } - - // Trying to measure the time of start bit and calculating the timeout - // for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU. - // So let's just wait the maximum time for the falling edge of a zero bit - // to arrive after we have detected the rising edge of the start bit. - timeout_count = ZERO_PULSE_TIME_OUT; - - // Detect possible edge indicating zero bit. - do { - if (SHA204_PIN_READ() == 0) { - // For an Atmel microcontroller this might be faster than "pulse_count++". - pulse_count = 2; - break; - } - } while (--timeout_count > 0); - - // Wait for rising edge of zero pulse before returning. Otherwise we might interpret - // its rising edge as the next start pulse. - if (pulse_count == 2) { - do { - if (SHA204_PIN_READ() != 0) { - break; - } - } while (timeout_count-- > 0); - } - - // Update byte at current buffer index. - else { - buffer[i] |= bit_mask; // received "one" bit - } - } - - if (status != SWI_FUNCTION_RETCODE_SUCCESS) { - break; - } - } - interrupts(); //swi_enable_interrupts(); - - if (status == SWI_FUNCTION_RETCODE_TIMEOUT) { - if (i > 0) - // Indicate that we timed out after having received at least one byte. - { - status = SWI_FUNCTION_RETCODE_RX_FAIL; - } - } - return status; -} - -/* Physical functions */ - -uint8_t atsha204Class::sha204p_wakeup() -{ - swi_set_signal_pin(0); - delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH); - swi_set_signal_pin(1); - delay(SHA204_WAKEUP_DELAY); - - return SHA204_SUCCESS; -} - -uint8_t atsha204Class::sha204p_sleep() -{ - return swi_send_byte(SHA204_SWI_FLAG_SLEEP); -} - -uint8_t atsha204Class::sha204p_resync(uint8_t size, uint8_t *response) -{ - delay(SHA204_SYNC_TIMEOUT); - return sha204p_receive_response(size, response); -} - -uint8_t atsha204Class::sha204p_receive_response(uint8_t size, uint8_t *response) -{ - uint8_t i; - uint8_t ret_code; - - for (i = 0; i < size; i++) { - response[i] = 0; - } - - (void) swi_send_byte(SHA204_SWI_FLAG_TX); - - ret_code = swi_receive_bytes(size, response); - if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) { - uint8_t count_byte; - count_byte = response[SHA204_BUFFER_POS_COUNT]; - if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) { - return SHA204_INVALID_SIZE; - } - - return SHA204_SUCCESS; - } - - // Translate error so that the Communication layer - // can distinguish between a real error or the - // device being busy executing a command. - if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) { - return SHA204_RX_NO_RESPONSE; - } else { - return SHA204_RX_FAIL; - } -} - -uint8_t atsha204Class::sha204p_send_command(uint8_t count, uint8_t * command) -{ - uint8_t ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); - if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) { - return SHA204_COMM_FAIL; - } - - return swi_send_bytes(count, command); -} - -/* Communication functions */ - -uint8_t atsha204Class::sha204c_wakeup(uint8_t *response) -{ - uint8_t ret_code = sha204p_wakeup(); - if (ret_code != SHA204_SUCCESS) { - return ret_code; - } - - ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response); - if (ret_code != SHA204_SUCCESS) { - return ret_code; - } - - // Verify status response. - if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) { - ret_code = SHA204_INVALID_SIZE; - } else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) { - ret_code = SHA204_COMM_FAIL; - } else { - if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) - || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) { - ret_code = SHA204_BAD_CRC; - } - } - if (ret_code != SHA204_SUCCESS) { - delay(SHA204_COMMAND_EXEC_MAX); - } - - return ret_code; -} - -uint8_t atsha204Class::sha204c_resync(uint8_t size, uint8_t *response) -{ - // Try to re-synchronize without sending a Wake token - // (step 1 of the re-synchronization process). - uint8_t ret_code = sha204p_resync(size, response); - if (ret_code == SHA204_SUCCESS) { - return ret_code; - } - - // We lost communication. Send a Wake pulse and try - // to receive a response (steps 2 and 3 of the - // re-synchronization process). - (void) sha204p_sleep(); - ret_code = sha204c_wakeup(response); - - // Translate a return value of success into one - // that indicates that the device had to be woken up - // and might have lost its TempKey. - return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); -} - -uint8_t atsha204Class::sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, - uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout) -{ - uint8_t ret_code = SHA204_FUNC_FAIL; - uint8_t ret_code_resync; - uint8_t n_retries_send; - uint8_t n_retries_receive; - uint8_t i; - uint8_t status_byte; - uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT]; - uint8_t count_minus_crc = count - SHA204_CRC_SIZE; - uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT; - volatile uint16_t timeout_countdown; - - // Append CRC. - sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc); - - // Retry loop for sending a command and receiving a response. - n_retries_send = SHA204_RETRY_COUNT + 1; - - while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) { - // Send command. - ret_code = sha204p_send_command(count, tx_buffer); - if (ret_code != SHA204_SUCCESS) { - if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { - return ret_code; // The device seems to be dead in the water. - } else { - continue; - } - } - - // Wait minimum command execution time and then start polling for a response. - delay(execution_delay); - - // Retry loop for receiving a response. - n_retries_receive = SHA204_RETRY_COUNT + 1; - while (n_retries_receive-- > 0) { - // Reset response buffer. - for (i = 0; i < rx_size; i++) { - rx_buffer[i] = 0; - } - - // Poll for response. - timeout_countdown = execution_timeout_us; - do { - ret_code = sha204p_receive_response(rx_size, rx_buffer); - timeout_countdown -= SHA204_RESPONSE_TIMEOUT; - } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE)); - - if (ret_code == SHA204_RX_NO_RESPONSE) { - // We did not receive a response. Re-synchronize and send command again. - if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) - // The device seems to be dead in the water. - { - return ret_code; - } else { - break; - } - } - - // Check whether we received a valid response. - if (ret_code == SHA204_INVALID_SIZE) { - // We see 0xFF for the count when communication got out of sync. - ret_code_resync = sha204c_resync(rx_size, rx_buffer); - if (ret_code_resync == SHA204_SUCCESS) - // We did not have to wake up the device. Try receiving response again. - { - continue; - } - if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) - // We could re-synchronize, but only after waking up the device. - // Re-send command. - { - break; - } else - // We failed to re-synchronize. - { - return ret_code; - } - } - - // We received a response of valid size. - // Check the consistency of the response. - ret_code = sha204c_check_crc(rx_buffer); - if (ret_code == SHA204_SUCCESS) { - // Received valid response. - if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) - // Received non-status response. We are done. - { - return ret_code; - } - - // Received status response. - status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS]; - - // Translate the three possible device status error codes - // into library return codes. - if (status_byte == SHA204_STATUS_BYTE_PARSE) { - return SHA204_PARSE_ERROR; - } - if (status_byte == SHA204_STATUS_BYTE_EXEC) { - return SHA204_CMD_FAIL; - } - if (status_byte == SHA204_STATUS_BYTE_COMM) { - // In case of the device status byte indicating a communication - // error this function exits the retry loop for receiving a response - // and enters the overall retry loop - // (send command / receive response). - ret_code = SHA204_STATUS_CRC; - break; - } - - // Received status response from CheckMAC, DeriveKey, GenDig, - // Lock, Nonce, Pause, UpdateExtra, or Write command. - return ret_code; - } - - else { - // Received response with incorrect CRC. - ret_code_resync = sha204c_resync(rx_size, rx_buffer); - if (ret_code_resync == SHA204_SUCCESS) - // We did not have to wake up the device. Try receiving response again. - { - continue; - } - if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) - // We could re-synchronize, but only after waking up the device. - // Re-send command. - { - break; - } else - // We failed to re-synchronize. - { - return ret_code; - } - } // block end of check response consistency - - } // block end of receive retry loop - - } // block end of send and receive retry loop - - return ret_code; -} - - -/* Marshaling functions */ - -uint8_t atsha204Class::sha204m_random(uint8_t * tx_buffer, uint8_t * rx_buffer, uint8_t mode) -{ - if (!tx_buffer || !rx_buffer || (mode > RANDOM_NO_SEED_UPDATE)) { - return SHA204_BAD_PARAM; - } - - tx_buffer[SHA204_COUNT_IDX] = RANDOM_COUNT; - tx_buffer[SHA204_OPCODE_IDX] = SHA204_RANDOM; - tx_buffer[RANDOM_MODE_IDX] = mode & RANDOM_SEED_UPDATE; - - tx_buffer[RANDOM_PARAM2_IDX] = - tx_buffer[RANDOM_PARAM2_IDX + 1] = 0; - - return sha204c_send_and_receive(&tx_buffer[0], RANDOM_RSP_SIZE, &rx_buffer[0], RANDOM_DELAY, - RANDOM_EXEC_MAX - RANDOM_DELAY); -} - -uint8_t atsha204Class::sha204m_dev_rev(uint8_t *tx_buffer, uint8_t *rx_buffer) -{ - if (!tx_buffer || !rx_buffer) { - return SHA204_BAD_PARAM; - } - - tx_buffer[SHA204_COUNT_IDX] = DEVREV_COUNT; - tx_buffer[SHA204_OPCODE_IDX] = SHA204_DEVREV; - - // Parameters are 0. - tx_buffer[DEVREV_PARAM1_IDX] = - tx_buffer[DEVREV_PARAM2_IDX] = - tx_buffer[DEVREV_PARAM2_IDX + 1] = 0; - - return sha204c_send_and_receive(&tx_buffer[0], DEVREV_RSP_SIZE, &rx_buffer[0], - DEVREV_DELAY, DEVREV_EXEC_MAX - DEVREV_DELAY); -} - -uint8_t atsha204Class::sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, - uint16_t address) -{ - uint8_t rx_size; - - if (!tx_buffer || !rx_buffer || ((zone & ~READ_ZONE_MASK) != 0) - || ((zone & READ_ZONE_MODE_32_BYTES) && (zone == SHA204_ZONE_OTP))) { - return SHA204_BAD_PARAM; - } - - address >>= 2; - if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_CONFIG) { - if (address > SHA204_ADDRESS_MASK_CONFIG) { - return SHA204_BAD_PARAM; - } - } else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_OTP) { - if (address > SHA204_ADDRESS_MASK_OTP) { - return SHA204_BAD_PARAM; - } - } else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_DATA) { - if (address > SHA204_ADDRESS_MASK) { - return SHA204_BAD_PARAM; - } - } - - tx_buffer[SHA204_COUNT_IDX] = READ_COUNT; - tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ; - tx_buffer[READ_ZONE_IDX] = zone; - tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK); - tx_buffer[READ_ADDR_IDX + 1] = 0; - - rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; - - return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, - READ_EXEC_MAX - READ_DELAY); -} - -uint8_t atsha204Class::sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, - uint8_t *data3, - uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) -{ - uint8_t poll_delay, poll_timeout, response_size; - uint8_t *p_buffer; - uint8_t len; - - uint8_t ret_code = sha204m_check_parameters(op_code, param1, param2, - datalen1, data1, datalen2, data2, datalen3, data3, - tx_size, tx_buffer, rx_size, rx_buffer); - if (ret_code != SHA204_SUCCESS) { - return ret_code; - } - - // Supply delays and response size. - switch (op_code) { - case SHA204_CHECKMAC: - poll_delay = CHECKMAC_DELAY; - poll_timeout = CHECKMAC_EXEC_MAX - CHECKMAC_DELAY; - response_size = CHECKMAC_RSP_SIZE; - break; - - case SHA204_DERIVE_KEY: - poll_delay = DERIVE_KEY_DELAY; - poll_timeout = DERIVE_KEY_EXEC_MAX - DERIVE_KEY_DELAY; - response_size = DERIVE_KEY_RSP_SIZE; - break; - - case SHA204_DEVREV: - poll_delay = DEVREV_DELAY; - poll_timeout = DEVREV_EXEC_MAX - DEVREV_DELAY; - response_size = DEVREV_RSP_SIZE; - break; - - case SHA204_GENDIG: - poll_delay = GENDIG_DELAY; - poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; - response_size = GENDIG_RSP_SIZE; - break; - - case SHA204_HMAC: - poll_delay = HMAC_DELAY; - poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY; - response_size = HMAC_RSP_SIZE; - break; - - case SHA204_LOCK: - poll_delay = LOCK_DELAY; - poll_timeout = LOCK_EXEC_MAX - LOCK_DELAY; - response_size = LOCK_RSP_SIZE; - break; - - case SHA204_MAC: - poll_delay = MAC_DELAY; - poll_timeout = MAC_EXEC_MAX - MAC_DELAY; - response_size = MAC_RSP_SIZE; - break; - - case SHA204_NONCE: - poll_delay = NONCE_DELAY; - poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY; - response_size = param1 == NONCE_MODE_PASSTHROUGH - ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG; - break; - - case SHA204_PAUSE: - poll_delay = PAUSE_DELAY; - poll_timeout = PAUSE_EXEC_MAX - PAUSE_DELAY; - response_size = PAUSE_RSP_SIZE; - break; - - case SHA204_RANDOM: - poll_delay = RANDOM_DELAY; - poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY; - response_size = RANDOM_RSP_SIZE; - break; - - case SHA204_READ: - poll_delay = READ_DELAY; - poll_timeout = READ_EXEC_MAX - READ_DELAY; - response_size = (param1 & SHA204_ZONE_COUNT_FLAG) - ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; - break; - - case SHA204_UPDATE_EXTRA: - poll_delay = UPDATE_DELAY; - poll_timeout = UPDATE_EXEC_MAX - UPDATE_DELAY; - response_size = UPDATE_RSP_SIZE; - break; - - case SHA204_WRITE: - poll_delay = WRITE_DELAY; - poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY; - response_size = WRITE_RSP_SIZE; - break; - - default: - poll_delay = 0; - poll_timeout = SHA204_COMMAND_EXEC_MAX; - response_size = rx_size; - } - - // Assemble command. - len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN; - p_buffer = tx_buffer; - *p_buffer++ = len; - *p_buffer++ = op_code; - *p_buffer++ = param1; - *p_buffer++ = param2 & 0xFF; - *p_buffer++ = param2 >> 8; - - if (datalen1 > 0) { - memcpy(p_buffer, data1, datalen1); - p_buffer += datalen1; - } - if (datalen2 > 0) { - memcpy(p_buffer, data2, datalen2); - p_buffer += datalen2; - } - if (datalen3 > 0) { - memcpy(p_buffer, data3, datalen3); - p_buffer += datalen3; - } - - sha204c_calculate_crc(len - SHA204_CRC_SIZE, tx_buffer, p_buffer); - - // Send command and receive response. - return sha204c_send_and_receive(&tx_buffer[0], response_size, - &rx_buffer[0], poll_delay, poll_timeout); -} - -uint8_t atsha204Class::sha204m_check_parameters(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, - uint8_t *data3, - uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) -{ -#ifdef SHA204_CHECK_PARAMETERS - - uint8_t len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN; - if (!tx_buffer || tx_size < len || rx_size < SHA204_RSP_SIZE_MIN || !rx_buffer) { - return SHA204_BAD_PARAM; - } - - if ((datalen1 > 0 && !data1) || (datalen2 > 0 && !data2) || (datalen3 > 0 && !data3)) { - return SHA204_BAD_PARAM; - } - - // Check parameters depending on op-code. - switch (op_code) { - case SHA204_CHECKMAC: - if ( - // no null pointers allowed - !data1 || !data2 - // No reserved bits should be set. - || (param1 | CHECKMAC_MODE_MASK) != CHECKMAC_MODE_MASK - // key_id > 15 not allowed - || param2 > SHA204_KEY_ID_MAX - ) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_DERIVE_KEY: - if (param2 > SHA204_KEY_ID_MAX) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_DEVREV: - break; - - case SHA204_GENDIG: - if ((param1 != GENDIG_ZONE_OTP) && (param1 != GENDIG_ZONE_DATA)) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_HMAC: - if ((param1 & ~HMAC_MODE_MASK) != 0) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_LOCK: - if (((param1 & ~LOCK_ZONE_MASK) != 0) - || ((param1 & LOCK_ZONE_NO_CRC) && (param2 != 0))) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_MAC: - if (((param1 & ~MAC_MODE_MASK) != 0) - || (((param1 & MAC_MODE_BLOCK2_TEMPKEY) == 0) && !data1)) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_NONCE: - if ( !data1 - || (param1 > NONCE_MODE_PASSTHROUGH) - || (param1 == NONCE_MODE_INVALID) - ) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_PAUSE: - break; - - case SHA204_RANDOM: - if (param1 > RANDOM_NO_SEED_UPDATE) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_READ: - if (((param1 & ~READ_ZONE_MASK) != 0) - || ((param1 & READ_ZONE_MODE_32_BYTES) && (param1 == SHA204_ZONE_OTP))) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_TEMPSENSE: - break; - - case SHA204_UPDATE_EXTRA: - if (param1 > UPDATE_CONFIG_BYTE_86) { - return SHA204_BAD_PARAM; - } - break; - - case SHA204_WRITE: - if (!data1 || ((param1 & ~WRITE_ZONE_MASK) != 0)) { - return SHA204_BAD_PARAM; - } - break; - - default: - // unknown op-code - return SHA204_BAD_PARAM; - } - - return SHA204_SUCCESS; - -#else - (void)rx_size; - (void)tx_size; - (void)tx_buffer; - (void)rx_buffer; - (void)param1; - (void)param2; - (void)data1; - (void)data2; - (void)data3; - (void)datalen1; - (void)datalen2; - (void)datalen3; - (void)op_code; - return SHA204_SUCCESS; -#endif -} - -/* CRC Calculator and Checker */ - -void atsha204Class::sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc) -{ - uint16_t crc_register = 0; - - crc_register = calculateAndUpdateCrc(length, data, crc_register); - crc[0] = (uint8_t) (crc_register & 0x00FF); - crc[1] = (uint8_t) (crc_register >> 8); -} - -uint8_t atsha204Class::sha204c_check_crc(uint8_t *response) -{ - uint8_t crc[SHA204_CRC_SIZE]; - uint8_t count = response[SHA204_BUFFER_POS_COUNT]; - - count -= SHA204_CRC_SIZE; - sha204c_calculate_crc(count, response, crc); - - return (crc[0] == response[count] && crc[1] == response[count + 1]) - ? SHA204_SUCCESS : SHA204_BAD_CRC; -} diff --git a/lib/MySensors/examples/SecurityPersonalizer/sha204_library.h b/lib/MySensors/examples/SecurityPersonalizer/sha204_library.h deleted file mode 100644 index 349d39cc..00000000 --- a/lib/MySensors/examples/SecurityPersonalizer/sha204_library.h +++ /dev/null @@ -1,467 +0,0 @@ -#include "Arduino.h" - -#ifndef sha204_library_H -#define sha204_library_H - -/* bitbang_config.h */ - -#define PORT_ACCESS_TIME (630) //! time it takes to toggle the pin at CPU clock of 16 MHz (ns) -#define START_PULSE_WIDTH (4340) //! width of start pulse (ns) -#define BIT_DELAY (4) //! delay macro for width of one pulse (start pulse or zero pulse, in ns) -#define RX_TX_DELAY (15) //! turn around time when switching from receive to transmit -#define START_PULSE_TIME_OUT (255) //! This value is decremented while waiting for the falling edge of a start pulse. -#define ZERO_PULSE_TIME_OUT (26) //! This value is decremented while waiting for the falling edge of a zero pulse. - -/* swi_phys.h */ - -#define SWI_FUNCTION_RETCODE_SUCCESS ((uint8_t) 0x00) //!< Communication with device succeeded. -#define SWI_FUNCTION_RETCODE_TIMEOUT ((uint8_t) 0xF1) //!< Communication timed out. -#define SWI_FUNCTION_RETCODE_RX_FAIL ((uint8_t) 0xF9) //!< Communication failed after at least one byte was received. - -/* sha204_physical.h */ - -#define SHA204_RSP_SIZE_MIN ((uint8_t) 4) //!< minimum number of bytes in response -#define SHA204_RSP_SIZE_MAX ((uint8_t) 35) //!< maximum size of response packet -#define SHA204_BUFFER_POS_COUNT (0) //!< buffer index of count byte in command or response -#define SHA204_BUFFER_POS_DATA (1) //!< buffer index of data in response -#define SHA204_WAKEUP_PULSE_WIDTH (uint8_t) (6.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! width of Wakeup pulse in 10 us units -#define SHA204_WAKEUP_DELAY (uint8_t) (3.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! delay between Wakeup pulse and communication in ms - -/* sha204_swi.c */ -#define SHA204_SWI_FLAG_CMD ((uint8_t) 0x77) //!< flag preceding a command -#define SHA204_SWI_FLAG_TX ((uint8_t) 0x88) //!< flag requesting a response -#define SHA204_SWI_FLAG_IDLE ((uint8_t) 0xBB) //!< flag requesting to go into Idle mode -#define SHA204_SWI_FLAG_SLEEP ((uint8_t) 0xCC) //!< flag requesting to go into Sleep mode - -/* sha204_comm_marshaling.h */ -// command op-code definitions -#define SHA204_CHECKMAC ((uint8_t) 0x28) //!< CheckMac command op-code -#define SHA204_DERIVE_KEY ((uint8_t) 0x1C) //!< DeriveKey command op-code -#define SHA204_DEVREV ((uint8_t) 0x30) //!< DevRev command op-code -#define SHA204_GENDIG ((uint8_t) 0x15) //!< GenDig command op-code -#define SHA204_HMAC ((uint8_t) 0x11) //!< HMAC command op-code -#define SHA204_LOCK ((uint8_t) 0x17) //!< Lock command op-code -#define SHA204_MAC ((uint8_t) 0x08) //!< MAC command op-code -#define SHA204_NONCE ((uint8_t) 0x16) //!< Nonce command op-code -#define SHA204_PAUSE ((uint8_t) 0x01) //!< Pause command op-code -#define SHA204_RANDOM ((uint8_t) 0x1B) //!< Random command op-code -#define SHA204_READ ((uint8_t) 0x02) //!< Read command op-code -#define SHA204_UPDATE_EXTRA ((uint8_t) 0x20) //!< UpdateExtra command op-code -#define SHA204_WRITE ((uint8_t) 0x12) //!< Write command op-code - -// packet size definitions -#define SHA204_RSP_SIZE_VAL ((uint8_t) 7) //!< size of response packet containing four bytes of data - -// parameter range definitions -#define SHA204_KEY_ID_MAX ((uint8_t) 15) //!< maximum value for key id -#define SHA204_OTP_BLOCK_MAX ((uint8_t) 1) //!< maximum value for OTP block - -// definitions for command packet indexes common to all commands -#define SHA204_COUNT_IDX ( 0) //!< command packet index for count -#define SHA204_OPCODE_IDX ( 1) //!< command packet index for op-code -#define SHA204_PARAM1_IDX ( 2) //!< command packet index for first parameter -#define SHA204_PARAM2_IDX ( 3) //!< command packet index for second parameter -#define SHA204_DATA_IDX ( 5) //!< command packet index for second parameter - -// zone definitions -#define SHA204_ZONE_CONFIG ((uint8_t) 0x00) //!< Configuration zone -#define SHA204_ZONE_OTP ((uint8_t) 0x01) //!< OTP (One Time Programming) zone -#define SHA204_ZONE_DATA ((uint8_t) 0x02) //!< Data zone -#define SHA204_ZONE_MASK ((uint8_t) 0x03) //!< Zone mask -#define SHA204_ZONE_COUNT_FLAG ((uint8_t) 0x80) //!< Zone bit 7 set: Access 32 bytes, otherwise 4 bytes. -#define SHA204_ZONE_ACCESS_4 ((uint8_t) 4) //!< Read or write 4 bytes. -#define SHA204_ZONE_ACCESS_32 ((uint8_t) 32) //!< Read or write 32 bytes. -#define SHA204_ADDRESS_MASK_CONFIG ( 0x001F) //!< Address bits 5 to 7 are 0 for Configuration zone. -#define SHA204_ADDRESS_MASK_OTP ( 0x000F) //!< Address bits 4 to 7 are 0 for OTP zone. -#define SHA204_ADDRESS_MASK ( 0x007F) //!< Address bit 7 to 15 are always 0. - -// CheckMAC command definitions -#define CHECKMAC_MODE_IDX SHA204_PARAM1_IDX //!< CheckMAC command index for mode -#define CHECKMAC_KEYID_IDX SHA204_PARAM2_IDX //!< CheckMAC command index for key identifier -#define CHECKMAC_CLIENT_CHALLENGE_IDX SHA204_DATA_IDX //!< CheckMAC command index for client challenge -#define CHECKMAC_CLIENT_RESPONSE_IDX (37) //!< CheckMAC command index for client response -#define CHECKMAC_DATA_IDX (69) //!< CheckMAC command index for other data -#define CHECKMAC_COUNT (84) //!< CheckMAC command packet size -#define CHECKMAC_MODE_MASK ((uint8_t) 0x27) //!< CheckMAC mode bits 3, 4, 6, and 7 are 0. -#define CHECKMAC_CLIENT_CHALLENGE_SIZE (32) //!< CheckMAC size of client challenge -#define CHECKMAC_CLIENT_RESPONSE_SIZE (32) //!< CheckMAC size of client response -#define CHECKMAC_OTHER_DATA_SIZE (13) //!< CheckMAC size of "other data" - -// DeriveKey command definitions -#define DERIVE_KEY_RANDOM_IDX SHA204_PARAM1_IDX //!< DeriveKey command index for random bit -#define DERIVE_KEY_TARGETKEY_IDX SHA204_PARAM2_IDX //!< DeriveKey command index for target slot -#define DERIVE_KEY_MAC_IDX SHA204_DATA_IDX //!< DeriveKey command index for optional MAC -#define DERIVE_KEY_COUNT_SMALL SHA204_CMD_SIZE_MIN //!< DeriveKey command packet size without MAC -#define DERIVE_KEY_COUNT_LARGE (39) //!< DeriveKey command packet size with MAC -#define DERIVE_KEY_RANDOM_FLAG ((uint8_t) 4) //!< DeriveKey 1. parameter -#define DERIVE_KEY_MAC_SIZE (32) //!< DeriveKey MAC size - -// DevRev command definitions -#define DEVREV_PARAM1_IDX SHA204_PARAM1_IDX //!< DevRev command index for 1. parameter (ignored) -#define DEVREV_PARAM2_IDX SHA204_PARAM2_IDX //!< DevRev command index for 2. parameter (ignored) -#define DEVREV_COUNT SHA204_CMD_SIZE_MIN //!< DevRev command packet size - -// GenDig command definitions -#define GENDIG_ZONE_IDX SHA204_PARAM1_IDX //!< GenDig command index for zone -#define GENDIG_KEYID_IDX SHA204_PARAM2_IDX //!< GenDig command index for key id -#define GENDIG_DATA_IDX SHA204_DATA_IDX //!< GenDig command index for optional data -#define GENDIG_COUNT SHA204_CMD_SIZE_MIN //!< GenDig command packet size without "other data" -#define GENDIG_COUNT_DATA (11) //!< GenDig command packet size with "other data" -#define GENDIG_OTHER_DATA_SIZE (4) //!< GenDig size of "other data" -#define GENDIG_ZONE_CONFIG ((uint8_t) 0) //!< GenDig zone id config -#define GENDIG_ZONE_OTP ((uint8_t) 1) //!< GenDig zone id OTP -#define GENDIG_ZONE_DATA ((uint8_t) 2) //!< GenDig zone id data - -// HMAC command definitions -#define HMAC_MODE_IDX SHA204_PARAM1_IDX //!< HMAC command index for mode -#define HMAC_KEYID_IDX SHA204_PARAM2_IDX //!< HMAC command index for key id -#define HMAC_COUNT SHA204_CMD_SIZE_MIN //!< HMAC command packet size -#define HMAC_MODE_MASK ((uint8_t) 0x74) //!< HMAC mode bits 0, 1, 3, and 7 are 0. - -// Lock command definitions -#define LOCK_ZONE_IDX SHA204_PARAM1_IDX //!< Lock command index for zone -#define LOCK_SUMMARY_IDX SHA204_PARAM2_IDX //!< Lock command index for summary -#define LOCK_COUNT SHA204_CMD_SIZE_MIN //!< Lock command packet size -#define LOCK_ZONE_NO_CONFIG ((uint8_t) 0x01) //!< Lock zone is OTP or Data -#define LOCK_ZONE_NO_CRC ((uint8_t) 0x80) //!< Lock command: Ignore summary. -#define LOCK_ZONE_MASK (0x81) //!< Lock parameter 1 bits 2 to 6 are 0. - -// Mac command definitions -#define MAC_MODE_IDX SHA204_PARAM1_IDX //!< MAC command index for mode -#define MAC_KEYID_IDX SHA204_PARAM2_IDX //!< MAC command index for key id -#define MAC_CHALLENGE_IDX SHA204_DATA_IDX //!< MAC command index for optional challenge -#define MAC_COUNT_SHORT SHA204_CMD_SIZE_MIN //!< MAC command packet size without challenge -#define MAC_COUNT_LONG (39) //!< MAC command packet size with challenge -#define MAC_MODE_BLOCK2_TEMPKEY ((uint8_t) 0x01) //!< MAC mode bit 0: second SHA block from TempKey -#define MAC_MODE_BLOCK1_TEMPKEY ((uint8_t) 0x02) //!< MAC mode bit 1: first SHA block from TempKey -#define MAC_MODE_SOURCE_FLAG_MATCH ((uint8_t) 0x04) //!< MAC mode bit 2: match TempKey.SourceFlag -#define MAC_MODE_PASSTHROUGH ((uint8_t) 0x07) //!< MAC mode bit 0-2: pass-through mode -#define MAC_MODE_INCLUDE_OTP_88 ((uint8_t) 0x10) //!< MAC mode bit 4: include first 88 OTP bits -#define MAC_MODE_INCLUDE_OTP_64 ((uint8_t) 0x20) //!< MAC mode bit 5: include first 64 OTP bits -#define MAC_MODE_INCLUDE_SN ((uint8_t) 0x40) //!< MAC mode bit 6: include serial number -#define MAC_CHALLENGE_SIZE (32) //!< MAC size of challenge -#define MAC_MODE_MASK ((uint8_t) 0x77) //!< MAC mode bits 3 and 7 are 0. - -// Nonce command definitions -#define NONCE_MODE_IDX SHA204_PARAM1_IDX //!< Nonce command index for mode -#define NONCE_PARAM2_IDX SHA204_PARAM2_IDX //!< Nonce command index for 2. parameter -#define NONCE_INPUT_IDX SHA204_DATA_IDX //!< Nonce command index for input data -#define NONCE_COUNT_SHORT (27) //!< Nonce command packet size for 20 bytes of data -#define NONCE_COUNT_LONG (39) //!< Nonce command packet size for 32 bytes of data -#define NONCE_MODE_MASK ((uint8_t) 3) //!< Nonce mode bits 2 to 7 are 0. -#define NONCE_MODE_SEED_UPDATE ((uint8_t) 0x00) //!< Nonce mode: update seed -#define NONCE_MODE_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Nonce mode: do not update seed -#define NONCE_MODE_INVALID ((uint8_t) 0x02) //!< Nonce mode 2 is invalid. -#define NONCE_MODE_PASSTHROUGH ((uint8_t) 0x03) //!< Nonce mode: pass-through -#define NONCE_NUMIN_SIZE (20) //!< Nonce data length -#define NONCE_NUMIN_SIZE_PASSTHROUGH (32) //!< Nonce data length in pass-through mode (mode = 3) - -// Pause command definitions -#define PAUSE_SELECT_IDX SHA204_PARAM1_IDX //!< Pause command index for Selector -#define PAUSE_PARAM2_IDX SHA204_PARAM2_IDX //!< Pause command index for 2. parameter -#define PAUSE_COUNT SHA204_CMD_SIZE_MIN //!< Pause command packet size - -// Random command definitions -#define RANDOM_MODE_IDX SHA204_PARAM1_IDX //!< Random command index for mode -#define RANDOM_PARAM2_IDX SHA204_PARAM2_IDX //!< Random command index for 2. parameter -#define RANDOM_COUNT SHA204_CMD_SIZE_MIN //!< Random command packet size -#define RANDOM_SEED_UPDATE ((uint8_t) 0x00) //!< Random mode for automatic seed update -#define RANDOM_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Random mode for no seed update - -// Read command definitions -#define READ_ZONE_IDX SHA204_PARAM1_IDX //!< Read command index for zone -#define READ_ADDR_IDX SHA204_PARAM2_IDX //!< Read command index for address -#define READ_COUNT SHA204_CMD_SIZE_MIN //!< Read command packet size -#define READ_ZONE_MASK ((uint8_t) 0x83) //!< Read zone bits 2 to 6 are 0. -#define READ_ZONE_MODE_32_BYTES ((uint8_t) 0x80) //!< Read mode: 32 bytes - -// UpdateExtra command definitions -#define UPDATE_MODE_IDX SHA204_PARAM1_IDX //!< UpdateExtra command index for mode -#define UPDATE_VALUE_IDX SHA204_PARAM2_IDX //!< UpdateExtra command index for new value -#define UPDATE_COUNT SHA204_CMD_SIZE_MIN //!< UpdateExtra command packet size -#define UPDATE_CONFIG_BYTE_86 ((uint8_t) 0x01) //!< UpdateExtra mode: update Config byte 86 - -// Write command definitions -#define WRITE_ZONE_IDX SHA204_PARAM1_IDX //!< Write command index for zone -#define WRITE_ADDR_IDX SHA204_PARAM2_IDX //!< Write command index for address -#define WRITE_VALUE_IDX SHA204_DATA_IDX //!< Write command index for data -#define WRITE_MAC_VS_IDX ( 9) //!< Write command index for MAC following short data -#define WRITE_MAC_VL_IDX (37) //!< Write command index for MAC following long data -#define WRITE_COUNT_SHORT (11) //!< Write command packet size with short data and no MAC -#define WRITE_COUNT_LONG (39) //!< Write command packet size with long data and no MAC -#define WRITE_COUNT_SHORT_MAC (43) //!< Write command packet size with short data and MAC -#define WRITE_COUNT_LONG_MAC (71) //!< Write command packet size with long data and MAC -#define WRITE_MAC_SIZE (32) //!< Write MAC size -#define WRITE_ZONE_MASK ((uint8_t) 0xC3) //!< Write zone bits 2 to 5 are 0. -#define WRITE_ZONE_WITH_MAC ((uint8_t) 0x40) //!< Write zone bit 6: write encrypted with MAC - -// Response size definitions -#define CHECKMAC_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of DeriveKey command -#define DERIVE_KEY_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of DeriveKey command -#define DEVREV_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of DevRev command returns 4 bytes -#define GENDIG_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of GenDig command -#define HMAC_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of HMAC command -#define LOCK_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Lock command -#define MAC_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of MAC command -#define NONCE_RSP_SIZE_SHORT SHA204_RSP_SIZE_MIN //!< response size of Nonce command with mode[0:1] = 3 -#define NONCE_RSP_SIZE_LONG SHA204_RSP_SIZE_MAX //!< response size of Nonce command -#define PAUSE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Pause command -#define RANDOM_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Random command -#define READ_4_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of Read command when reading 4 bytes -#define READ_32_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Read command when reading 32 bytes -#define TEMP_SENSE_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of TempSense command returns 4 bytes -#define UPDATE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of UpdateExtra command -#define WRITE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Write command - -// command timing definitions for minimum execution times (ms) -#define CHECKMAC_DELAY ((uint8_t) (12.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define DERIVE_KEY_DELAY ((uint8_t) (14.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define DEVREV_DELAY ((uint8_t) ( 0.4 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define GENDIG_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define HMAC_DELAY ((uint8_t) (27.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define LOCK_DELAY ((uint8_t) ( 5.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define MAC_DELAY ((uint8_t) (12.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define NONCE_DELAY ((uint8_t) (22.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define PAUSE_DELAY ((uint8_t) ( 0.4 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define RANDOM_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define READ_DELAY ((uint8_t) ( 0.4 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define TEMP_SENSE_DELAY ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define UPDATE_DELAY ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) -#define WRITE_DELAY ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) - -// command timing definitions for maximum execution times (ms) -#define CHECKMAC_EXEC_MAX ((uint8_t) (38.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define DERIVE_KEY_EXEC_MAX ((uint8_t) (62.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define DEVREV_EXEC_MAX ((uint8_t) ( 2.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define GENDIG_EXEC_MAX ((uint8_t) (43.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define HMAC_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define LOCK_EXEC_MAX ((uint8_t) (24.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define MAC_EXEC_MAX ((uint8_t) (35.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define NONCE_EXEC_MAX ((uint8_t) (60.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define PAUSE_EXEC_MAX ((uint8_t) ( 2.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define RANDOM_EXEC_MAX ((uint8_t) (50.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define READ_EXEC_MAX ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define TEMP_SENSE_EXEC_MAX ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define UPDATE_EXEC_MAX ((uint8_t) ( 6.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) -#define WRITE_EXEC_MAX ((uint8_t) (42.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) - -/* from sha204_config.h */ - -#define CPU_CLOCK_DEVIATION_POSITIVE (1.01) -#define CPU_CLOCK_DEVIATION_NEGATIVE (0.99) -#define SHA204_RETRY_COUNT (1) -#define SWI_RECEIVE_TIME_OUT ((uint16_t) 163) //! #START_PULSE_TIME_OUT in us instead of loop counts -#define SWI_US_PER_BYTE ((uint16_t) 313) //! It takes 312.5 us to send a byte (9 single-wire bits / 230400 Baud * 8 flag bits). -#define SHA204_SYNC_TIMEOUT ((uint8_t) 85)//! delay before sending a transmit flag in the synchronization routine -#define SHA204_RESPONSE_TIMEOUT ((uint16_t) SWI_RECEIVE_TIME_OUT + SWI_US_PER_BYTE) //! SWI response timeout is the sum of receive timeout and the time it takes to send the TX flag. - -/* from sha204_comm.h */ - -#define SHA204_COMMAND_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) //! maximum command delay -#define SHA204_CMD_SIZE_MIN ((uint8_t) 7) //! minimum number of bytes in command (from count byte to second CRC byte) -#ifndef SHA204_CMD_SIZE_MAX -#define SHA204_CMD_SIZE_MAX ((uint8_t) 84) //! maximum size of command packet (CheckMac) -#endif -#define SHA204_CRC_SIZE ((uint8_t) 2) //! number of CRC bytes -#define SHA204_BUFFER_POS_STATUS (1) //! buffer index of status byte in status response -#define SHA204_BUFFER_POS_DATA (1) //! buffer index of first data byte in data response -#define SHA204_STATUS_BYTE_WAKEUP ((uint8_t) 0x11) //! command parse error -#define SHA204_STATUS_BYTE_PARSE ((uint8_t) 0x03) //! command parse error -#define SHA204_STATUS_BYTE_EXEC ((uint8_t) 0x0F) //! command execution error -#define SHA204_STATUS_BYTE_COMM ((uint8_t) 0xFF) //! communication error - -/* EEPROM Addresses */ -/* Configuration Zone */ -#define ADDRESS_SN03 0 // SN[0:3] are bytes 0->3 of configuration zone -#define ADDRESS_RevNum 4 // bytes 4->7 of config zone are RevNum -#define ADDRESS_SN47 8 // SN[4:7] are bytes 8->11 of config zone -#define ADDRESS_SN8 12 // SN[8] is byte 12 of config zone, should be 0xEE -#define ADDRESS_I2CEN 14 // I2C Enable, bit 0 represents I2C enable status -#define ADDRESS_I2CADD 16 // Defines I2C address of SHA204 -#define ADDRESS_OTPMODE 18 // Sets the One-time-programmable mode -#define ADDRESS_SELECTOR 19 // Controls writability of Selector - -/* Low level HW access macros */ -/* function calls is not working, as it will have too much overhead */ -#if !defined(ARDUINO_ARCH_AVR) // For everything else than AVR use pinMode / digitalWrite -#define SHA204_SET_OUTPUT() pinMode(device_pin, OUTPUT) -#define SHA204_SET_INPUT() pinMode(device_pin, INPUT) -#define SHA204_POUT_HIGH() digitalWrite(device_pin, HIGH) -#define SHA204_POUT_LOW() digitalWrite(device_pin, LOW) -#define SHA204_PIN_READ() digitalRead(device_pin) -#else -#define SHA204_SET_INPUT() *device_port_DDR &= ~device_pin -#define SHA204_SET_OUTPUT() *device_port_DDR |= device_pin -#define SHA204_POUT_HIGH() *device_port_OUT |= device_pin -#define SHA204_POUT_LOW() *device_port_OUT &= ~device_pin -#define SHA204_PIN_READ() (*device_port_IN & device_pin) -#endif - -/** - * atsha204Class class - */ -class atsha204Class -{ -private: - uint8_t device_pin; -#ifdef ARDUINO_ARCH_AVR - volatile uint8_t *device_port_DDR, *device_port_OUT, *device_port_IN; -#endif - void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc); - uint8_t sha204c_check_crc(uint8_t *response); - void swi_set_signal_pin(uint8_t is_high); - uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer); - uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer); - uint8_t swi_send_byte(uint8_t value); - uint8_t sha204p_receive_response(uint8_t size, uint8_t *response); - uint8_t sha204p_wakeup(); - uint8_t sha204p_send_command(uint8_t count, uint8_t * command); - uint8_t sha204p_sleep(); - uint8_t sha204p_resync(uint8_t size, uint8_t *response); - - -public: - /** - * @brief Constructor - * - * @param[in] pin The pin to use for communication - */ - explicit atsha204Class(uint8_t pin); - - /** - * @brief Wake up device - * - * @param response The response from the device - * - * @return Error code (SHA204_SUCCESS if OK) - */ - uint8_t sha204c_wakeup(uint8_t *response); - - /** - * @brief Send and receive data - * - * @param tx_buffer The transmit buffer - * @param[in] rx_size The receive size - * @param rx_buffer The receive buffer - * @param[in] execution_delay The execution delay - * @param[in] execution_timeout The execution timeout - * - * @return Error code (SHA204_SUCCESS if OK) - */ - uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, - uint8_t execution_delay, uint8_t execution_timeout); - - /** - * @brief Resyncronize the device - * - * @param[in] size The size of the response buffer - * @param response The response - * - * @return Error code (SHA204_SUCCESS if OK) - */ - uint8_t sha204c_resync(uint8_t size, uint8_t *response); - - /** - * @brief Generate random data - * - * @param tx_buffer The transmit buffer - * @param rx_buffer The receive buffer - * @param[in] mode The mode - * - * @return Error code (SHA204_SUCCESS if OK) - */ - uint8_t sha204m_random(uint8_t * tx_buffer, uint8_t * rx_buffer, uint8_t mode); - - /** - * @brief Read device revision - * - * @param tx_buffer The transmit buffer - * @param rx_buffer The receive buffer - * - * @return Error code (SHA204_SUCCESS if OK) - */ - uint8_t sha204m_dev_rev(uint8_t *tx_buffer, uint8_t *rx_buffer); - - /** - * @brief Read from device - * - * @param tx_buffer The transmit buffer - * @param rx_buffer The receive buffer - * @param[in] zone The zone - * @param[in] address The address - * - * @return Error code (SHA204_SUCCESS if OK) - */ - uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address); - - /** - * @brief Execute command - * - * @param[in] op_code The operation code - * @param[in] param1 The parameter 1 - * @param[in] param2 The parameter 2 - * @param[in] datalen1 The datalen 1 - * @param data1 The data 1 - * @param[in] datalen2 The datalen 2 - * @param data2 The data 2 - * @param[in] datalen3 The datalen 3 - * @param data3 The data 3 - * @param[in] tx_size The transmit size - * @param tx_buffer The transmit buffer - * @param[in] rx_size The receive size - * @param rx_buffer The receive buffer - * - * @return Error code (SHA204_SUCCESS if OK) - */ - uint8_t sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, - uint8_t *data3, - uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); - - /** - * @brief Validate parameters - * - * @param[in] op_code The operation code - * @param[in] param1 The parameter 1 - * @param[in] param2 The parameter 2 - * @param[in] datalen1 The datalen 1 - * @param data1 The data 1 - * @param[in] datalen2 The datalen 2 - * @param data2 The data 2 - * @param[in] datalen3 The datalen 3 - * @param data3 The data 3 - * @param[in] tx_size The transmit size - * @param tx_buffer The transmit buffer - * @param[in] rx_size The receive size - * @param rx_buffer The receive buffer - * - * @return Error code (SHA204_SUCCESS if OK) - */ - uint8_t sha204m_check_parameters(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, - uint8_t *data3, - uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); - - /** - * @brief Gets the serial number. - * - * @param response The response - * - * @return The serial number - */ - uint8_t getSerialNumber(uint8_t *response); - - /** - * @brief Calculates and update crc. - * - * @param[in] length The length - * @param data The data - * @param[in] current_crc The current crc - * - * @return The updated crc - */ - uint16_t calculateAndUpdateCrc(uint8_t length, uint8_t *data, uint16_t current_crc); - -}; - -#endif diff --git a/lib/MySensors/examples/SensebenderGatewaySerial/SensebenderGatewaySerial.ino b/lib/MySensors/examples/SensebenderGatewaySerial/SensebenderGatewaySerial.ino deleted file mode 100644 index 9514569e..00000000 --- a/lib/MySensors/examples/SensebenderGatewaySerial/SensebenderGatewaySerial.ino +++ /dev/null @@ -1,281 +0,0 @@ -/** -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -******************************* -* -* DESCRIPTION -* The ArduinoGateway prints data received from sensors on the serial link. -* The gateway accepts input on serial which will be sent out on radio network. -* -* This GW code is designed for Sensebender GateWay / (Arduino Zero variant) -* -* Wire connections (OPTIONAL): -* - Inclusion button should be connected to SW2 -* -* LEDs on board (default assignments): -* - Orange: USB RX/TX - Blink when receiving / transmitting on USB CDC device -* - Yellow: RX - Blink fast on radio message received. In inclusion mode will blink fast only on presentation received -* - Green : TX - Blink fast on radio message transmitted. In inclusion mode will blink slowly -* - Red : ERR - Fast blink on error during transmission error or receive crc error -* - Blue : free - (use with LED_BLUE macro) -* -*/ - -#define SKETCH_VERSION "0.2" -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -// Set LOW transmit power level as default, if you have an amplified NRF-module and -// power your radio separately with a good regulator you can turn up PA level. -#define MY_RF24_PA_LEVEL RF24_PA_HIGH - -// Enable serial gateway -#define MY_GATEWAY_SERIAL - -// Define a lower baud rate for Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & Sensebender) -#if F_CPU == 8000000L -#define MY_BAUD_RATE 38400 -#endif - -// Enable inclusion mode -#define MY_INCLUSION_MODE_FEATURE -// Enable Inclusion mode button on gateway -#define MY_INCLUSION_BUTTON_FEATURE - -// Inverses behavior of inclusion button (if using external pullup) -//#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP - -// Set inclusion mode duration (in seconds) -#define MY_INCLUSION_MODE_DURATION 60 -// Digital pin used for inclusion mode button -//#define MY_INCLUSION_MODE_BUTTON_PIN 3 - -// Set blinking period -#define MY_DEFAULT_LED_BLINK_PERIOD 300 - -// Inverses the behavior of leds -//#define MY_WITH_LEDS_BLINKING_INVERSE - -// Flash leds on rx/tx/err -// Uncomment to override default HW configurations -//#define MY_DEFAULT_ERR_LED_PIN 4 // Error led pin -//#define MY_DEFAULT_RX_LED_PIN 6 // Receive led pin -//#define MY_DEFAULT_TX_LED_PIN 5 // the PCB, on board LED - -#include -#include -#include - -Sd2Card card; - -#define EEPROM_VERIFICATION_ADDRESS 0x01 - -static uint8_t num_of_leds = 5; -static uint8_t leds[] = {LED_BLUE, LED_RED, LED_GREEN, LED_YELLOW, LED_ORANGE}; - -void setup() -{ - // Setup locally attached sensors -} - -void presentation() -{ - // Present locally attached sensors -} - -void loop() -{ - // Send locally attached sensor data here -} - - -void preHwInit() -{ - - pinMode(MY_SWC1, INPUT_PULLUP); - pinMode(MY_SWC2, INPUT_PULLUP); - if (digitalRead(MY_SWC1) && digitalRead(MY_SWC2)) { - return; - } - - uint8_t tests = 0; - - for (int i=0; i< num_of_leds; i++) { - pinMode(leds[i], OUTPUT); - } - if (digitalRead(MY_SWC1)) { - uint8_t led_state = 0; - while (!Serial) { - digitalWrite(LED_BLUE, led_state); - led_state ^= 0x01; - delay(500); - } // Wait for USB to be connected, before spewing out data. - } - digitalWrite(LED_BLUE, LOW); - if (Serial) { - Serial.println("Sensebender GateWay test routine"); - Serial.print("MySensors core version : "); - Serial.println(MYSENSORS_LIBRARY_VERSION); - Serial.print("GateWay sketch version : "); - Serial.println(SKETCH_VERSION); - Serial.println("----------------------------------"); - Serial.println(); - } - if (testSha204()) { - digitalWrite(LED_GREEN, HIGH); - tests++; - } - if (testSDCard()) { - digitalWrite(LED_YELLOW, HIGH); - tests++; - } - - if (testEEProm()) { - digitalWrite(LED_ORANGE, HIGH); - tests++; - } - if (testAnalog()) { - digitalWrite(LED_BLUE, HIGH); - tests++; - } - if (tests == 4) { - while(1) { - for (int i=0; i SHA204 "); - } - atsha204_init(MY_SIGNING_ATSHA204_PIN); - ret_code = atsha204_wakeup(rx_buffer); - - if (ret_code == SHA204_SUCCESS) { - ret_code = atsha204_getSerialNumber(rx_buffer); - if (ret_code != SHA204_SUCCESS) { - if (Serial) { - Serial.println(F("Failed to obtain device serial number. Response: ")); - } - Serial.println(ret_code, HEX); - } else { - if (Serial) { - Serial.print(F("Ok (serial : ")); - for (int i=0; i<9; i++) { - if (rx_buffer[i] < 0x10) { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[i], HEX); - } - Serial.println(")"); - } - return true; - } - } else { - if (Serial) { - Serial.println(F("Failed to wakeup SHA204")); - } - } - return false; -} - -bool testSDCard() -{ - if (Serial) { - Serial.print("- > SD CARD "); - } - if (!card.init(SPI_HALF_SPEED, MY_SDCARD_CS)) { - if (Serial) { - Serial.println("SD CARD did not initialize!"); - } - } else { - if (Serial) { - Serial.print("SD Card initialized correct! - "); - Serial.print("type detected : "); - switch(card.type()) { - case SD_CARD_TYPE_SD1: - Serial.println("SD1"); - break; - case SD_CARD_TYPE_SD2: - Serial.println("SD2"); - break; - case SD_CARD_TYPE_SDHC: - Serial.println("SDHC"); - break; - default: - Serial.println("Unknown"); - } - } - return true; - } - return false; -} - -bool testEEProm() -{ - uint8_t eeprom_d1, eeprom_d2; - SerialUSB.print(" -> EEPROM "); - eeprom_d1 = hwReadConfig(EEPROM_VERIFICATION_ADDRESS); - delay(500); - eeprom_d1 = ~eeprom_d1; // invert the bits - hwWriteConfig(EEPROM_VERIFICATION_ADDRESS, eeprom_d1); - delay(500); - eeprom_d2 = hwReadConfig(EEPROM_VERIFICATION_ADDRESS); - if (eeprom_d1 == eeprom_d2) { - SerialUSB.println("PASSED"); - hwWriteConfig(EEPROM_VERIFICATION_ADDRESS, ~eeprom_d1); - return true; - } - SerialUSB.println("FAILED!"); - return false; -} - -bool testAnalog() -{ - int bat_detect = analogRead(MY_BAT_DETECT); - Serial.print("-> analog : "); - Serial.print(bat_detect); - if (bat_detect < 400 || bat_detect > 650) { - Serial.println(" Failed"); - return false; - } - Serial.println(" Passed"); - return true; -} diff --git a/lib/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino b/lib/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino deleted file mode 100644 index 5f5698df..00000000 --- a/lib/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino +++ /dev/null @@ -1,198 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * Arduino soil moisture based on gypsum sensor/resistive sensor to avoid electric catalyse in soil - * Required to interface the sensor: 2 * 4.7kOhm + 2 * 1N4148 - * - * Gypsum sensor and calibration: - * DIY: See http://vanderleevineyard.com/1/category/vinduino/1.html - * Built: Davis / Watermark 200SS - * http://www.cooking-hacks.com/watermark-soil-moisture-sensor?_bksrc=item2item&_bkloc=product - * http://www.irrometer.com/pdf/supportmaterial/sensors/voltage-WM-chart.pdf - * cb (centibar) http://www.irrometer.com/basics.html - * 0-10 Saturated Soil. Occurs for a day or two after irrigation - * 10-20 Soil is adequately wet (except coarse sands which are drying out at this range) - * 30-60 Usual range to irrigate or water (except heavy clay soils). - * 60-100 Usual range to irrigate heavy clay soils - * 100-200 Soil is becoming dangerously dry for maximum production. Proceed with caution. - * - * Connection: - * D6, D7: alternative powering to avoid sensor degradation - * A0, A1: alternative resistance measuring - * - * Based on: - * "Vinduino" portable soil moisture sensor code V3.00 - * Date December 31, 2012 - * Reinier van der Lee and Theodore Kaskalis - * www.vanderleevineyard.com - * Contributor: epierre - */ - -// Copyright (C) 2015, Reinier van der Lee -// www.vanderleevineyard.com - -// 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 -// 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. - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include // Conversion equation from resistance to % -#include - -// Setting up format for reading 3 soil sensors -#define NUM_READS (int)10 // Number of sensor reads for filtering -#define CHILD_ID 0 - -MyMessage msg(CHILD_ID, V_LEVEL); -uint32_t SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) - -long buffer[NUM_READS]; -int idx; - -/// @brief Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs) -typedef struct { - int moisture; //!< Moisture - long resistance; //!< Resistance -} values; - -const long knownResistor = 4700; // Constant value of known resistor in Ohms - -int supplyVoltage; // Measured supply voltage -int sensorVoltage; // Measured sensor voltage - -values valueOf[NUM_READS]; // Calculated moisture percentages and resistances to be sorted and filtered - -int i; // Simple index variable - -void setup() -{ - // initialize the digital pins as an output. - // Pin 6,7 is for sensor 1 - // initialize the digital pin as an output. - // Pin 6 is sense resistor voltage supply 1 - pinMode(6, OUTPUT); - - // initialize the digital pin as an output. - // Pin 7 is sense resistor voltage supply 2 - pinMode(7, OUTPUT); -} - -void presentation() -{ - sendSketchInfo("Soil Moisture Sensor Reverse Polarity", "1.0"); - present(CHILD_ID, S_MOISTURE); -} - -void loop() -{ - - measure(6,7,1); - Serial.print ("\t"); - Serial.println (average()); - long read1 = average(); - - measure(7,6,0); - Serial.print ("\t"); - Serial.println (average()); - long read2= average(); - - long sensor1 = (read1 + read2)/2; - - Serial.print ("resistance bias =" ); - Serial.println (read1-read2); - Serial.print ("sensor bias compensated value = "); - Serial.println (sensor1); - Serial.println (); - - //send back the values - send(msg.set((int32_t)ceil(sensor1))); - // delay until next measurement (msec) - sleep(SLEEP_TIME); -} - -void measure (int phase_b, int phase_a, int analog_input) -{ - // read sensor, filter, and calculate resistance value - // Noise filter: median filter - - for (i=0; i= NUM_READS) { - idx = 0; - } -} - -long average() -{ - long sum = 0; - for (int cnt = 0; cnt < NUM_READS; cnt++) { - sum += buffer[cnt]; - } - return (long)(sum / NUM_READS); -} diff --git a/lib/MySensors/examples/UVSensor/UVSensor.ino b/lib/MySensors/examples/UVSensor/UVSensor.ino deleted file mode 100644 index 73031159..00000000 --- a/lib/MySensors/examples/UVSensor/UVSensor.ino +++ /dev/null @@ -1,111 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - epierre - * Contribution: bulldoglowell, gizmocuz - * - * DESCRIPTION - * Arduino UVM-30A - * Index table taken from: http://www.elecrow.com/sensors-c-111/environment-c-111_112/uv-sensor-moduleuvm30a-p-716.html - * Because this table is pretty lineair, we can calculate a UVI with one decimal - * - * Connect sensor: - * - * + >>> 5V - * - >>> GND - * out >>> A0 - * - * License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define UV_SENSOR_ANALOG_PIN 0 - -#define CHILD_ID_UV 0 - -uint32_t SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) - -MyMessage uvMsg(CHILD_ID_UV, V_UV); - -uint32_t lastSend =0; -float uvIndex; -float lastUV = -1; -uint16_t uvIndexValue [12] = { 50, 227, 318, 408, 503, 606, 696, 795, 881, 976, 1079, 1170}; - - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("UV Sensor", "1.2"); - - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_UV, S_UV); -} - -void loop() -{ - uint32_t currentTime = millis(); - - uint16_t uv = analogRead(UV_SENSOR_ANALOG_PIN);// Get UV value - if (uv>1170) { - uv=1170; - } - - //Serial.print("UV Analog reading: "); - //Serial.println(uv); - - int i; - for (i = 0; i < 12; i++) { - if (uv <= uvIndexValue[i]) { - uvIndex = i; - break; - } - } - - //calculate 1 decimal if possible - if (i>0) { - float vRange=uvIndexValue[i]-uvIndexValue[i-1]; - float vCalc=uv-uvIndexValue[i-1]; - uvIndex+=(1.0/vRange)*vCalc-1.0; - } - - //Serial.print("UVI: "); - //Serial.println(uvIndex,2); - - //Send value to gateway if changed, or at least every 5 minutes - if ((uvIndex != lastUV)||(currentTime-lastSend >= 5UL*60UL*1000UL)) { - lastSend=currentTime; - send(uvMsg.set(uvIndex,2)); - lastUV = uvIndex; - } - - sleep(SLEEP_TIME); -} diff --git a/lib/MySensors/examples/VibrationSensor/VibrationSensor.ino b/lib/MySensors/examples/VibrationSensor/VibrationSensor.ino deleted file mode 100644 index 24367dfe..00000000 --- a/lib/MySensors/examples/VibrationSensor/VibrationSensor.ino +++ /dev/null @@ -1,101 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * DESCRIPTION - * - * Vibration Sensor - * - * connect the sensor as follows : - * - * VCC >>> 5V - * S >>> D3 - * GND >>> GND - * - * Based on: http://www.dfrobot.com/wiki/index.php/DFRobot_Digital_Vibration_Sensor_V2_SKU:DFR0027 - * Contributor: epierre - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include -#include - -#define CHILD_ID_VIBRATION 0 -#define VIBRATION_SENSOR_DIGITAL_PIN 3 -#define SensorLED 13 - -uint32_t SLEEP_TIME = 10*1000; // Sleep time between reads (in seconds) - -//VARIABLES -int val = 0; // variable to store the value coming from the sensor -float valVIBRATION =0.0; -float lastVIBRATION =0.0; -unsigned char state = 0; - -MyMessage vibrationMsg(CHILD_ID_VIBRATION, V_LEVEL); - -void setup() -{ - pinMode(VIBRATION_SENSOR_DIGITAL_PIN, INPUT); - attachInterrupt(digitalPinToInterrupt(VIBRATION_SENSOR_DIGITAL_PIN), blink, - FALLING); // Trigger the blink function when the falling edge is detected - pinMode(SensorLED, OUTPUT); -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("VIBRATION Sensor", "1.0"); - - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_VIBRATION, S_VIBRATION); -} - -void loop() -{ - - if(state>=40) { // basically below 40 so ignire basic level - send(vibrationMsg.set(int16_t(state))); - state = 0; - digitalWrite(SensorLED,HIGH); - } else { - state = 0; - digitalWrite(SensorLED,LOW); - } - - - // Power down the radio. Note that the radio will get powered back up - // on the next write() call. - delay(1000); //delay to allow serial to fully print before sleep - - sleep(SLEEP_TIME); //sleep for: sleepTime -} - -void blink()//Interrupts function -{ - state++; -} diff --git a/lib/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino b/lib/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino deleted file mode 100644 index c80a4e8c..00000000 --- a/lib/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino +++ /dev/null @@ -1,194 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - ******************************* - * - * REVISION HISTORY - * Version 1.0 - Henrik Ekblad - * Version 1.1 - GizMoCuz - * - * DESCRIPTION - * Use this sensor to measure volume and flow of your house water meter. - * You need to set the correct pulsefactor of your meter (pulses per m3). - * The sensor starts by fetching current volume reading from gateway (VAR 1). - * Reports both volume and flow back to gateway. - * - * Unfortunately millis() won't increment when the Arduino is in - * sleepmode. So we cannot make this sensor sleep if we also want - * to calculate/report flow. - * http://www.mysensors.org/build/pulse_water - */ - -// Enable debug prints to serial monitor -#define MY_DEBUG - -// Enable and select radio type attached -#define MY_RADIO_RF24 -//#define MY_RADIO_NRF5_ESB -//#define MY_RADIO_RFM69 -//#define MY_RADIO_RFM95 - -#include - -#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) - -#define PULSE_FACTOR 1000 // Number of blinks per m3 of your meter (One rotation/liter) - -#define SLEEP_MODE false // flowvalue can only be reported when sleep mode is false. - -#define MAX_FLOW 40 // Max flow (l/min) value to report. This filters outliers. - -#define CHILD_ID 1 // Id of the sensor child - -uint32_t SEND_FREQUENCY = - 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. - -MyMessage flowMsg(CHILD_ID,V_FLOW); -MyMessage volumeMsg(CHILD_ID,V_VOLUME); -MyMessage lastCounterMsg(CHILD_ID,V_VAR1); - -double ppl = ((double)PULSE_FACTOR)/1000; // Pulses per liter - -volatile uint32_t pulseCount = 0; -volatile uint32_t lastBlink = 0; -volatile double flow = 0; -bool pcReceived = false; -uint32_t oldPulseCount = 0; -double oldflow = 0; -double oldvolume =0; -uint32_t lastSend =0; -uint32_t lastPulse =0; - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#define IRQ_HANDLER_ATTR ICACHE_RAM_ATTR -#else -#define IRQ_HANDLER_ATTR -#endif - -void IRQ_HANDLER_ATTR onPulse() -{ - if (!SLEEP_MODE) { - uint32_t newBlink = micros(); - uint32_t interval = newBlink-lastBlink; - - if (interval!=0) { - lastPulse = millis(); - if (interval<500000L) { - // Sometimes we get interrupt on RISING, 500000 = 0.5 second debounce ( max 120 l/min) - return; - } - flow = (60000000.0 /interval) / ppl; - } - lastBlink = newBlink; - } - pulseCount++; -} - -void setup() -{ - // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion) - pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP); - - pulseCount = oldPulseCount = 0; - - // Fetch last known pulse count value from gw - request(CHILD_ID, V_VAR1); - - lastSend = lastPulse = millis(); - - attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, FALLING); -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Water Meter", "1.1"); - - // Register this device as Water flow sensor - present(CHILD_ID, S_WATER); -} - -void loop() -{ - uint32_t currentTime = millis(); - - // Only send values at a maximum frequency or woken up from sleep - if (SLEEP_MODE || (currentTime - lastSend > SEND_FREQUENCY)) { - lastSend=currentTime; - - if (!pcReceived) { - //Last Pulsecount not yet received from controller, request it again - request(CHILD_ID, V_VAR1); - return; - } - - if (!SLEEP_MODE && flow != oldflow) { - oldflow = flow; - - Serial.print("l/min:"); - Serial.println(flow); - - // Check that we don't get unreasonable large flow value. - // could happen when long wraps or false interrupt triggered - if (flow<((uint32_t)MAX_FLOW)) { - send(flowMsg.set(flow, 2)); // Send flow value to gw - } - } - - // No Pulse count received in 2min - if(currentTime - lastPulse > 120000) { - flow = 0; - } - - // Pulse count has changed - if ((pulseCount != oldPulseCount)||(!SLEEP_MODE)) { - oldPulseCount = pulseCount; - - Serial.print("pulsecount:"); - Serial.println(pulseCount); - - send(lastCounterMsg.set(pulseCount)); // Send pulsecount value to gw in VAR1 - - double volume = ((double)pulseCount/((double)PULSE_FACTOR)); - if ((volume != oldvolume)||(!SLEEP_MODE)) { - oldvolume = volume; - - Serial.print("volume:"); - Serial.println(volume, 3); - - send(volumeMsg.set(volume, 3)); // Send volume value to gw - } - } - } - if (SLEEP_MODE) { - sleep(SEND_FREQUENCY, false); - } -} - -void receive(const MyMessage &message) -{ - if (message.getType()==V_VAR1) { - uint32_t gwPulseCount=message.getULong(); - pulseCount += gwPulseCount; - flow=oldflow=0; - Serial.print("Received last pulse count from gw:"); - Serial.println(pulseCount); - pcReceived = true; - } -} - diff --git a/lib/MySensors/hal/architecture/AVR/MyHwAVR.cpp b/lib/MySensors/hal/architecture/AVR/MyHwAVR.cpp deleted file mode 100644 index e14adfb0..00000000 --- a/lib/MySensors/hal/architecture/AVR/MyHwAVR.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHwAVR.h" - -bool hwInit(void) -{ -#if !defined(MY_DISABLED_SERIAL) - MY_SERIALDEVICE.begin(MY_BAUD_RATE); -#if defined(MY_GATEWAY_SERIAL) - while (!MY_SERIALDEVICE) {} -#endif -#endif - return true; -} - -#define WDTO_SLEEP_FOREVER (0xFFu) - -volatile uint8_t _wokeUpByInterrupt = - INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu. -volatile uint8_t _wakeUp1Interrupt = - INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback. -volatile uint8_t _wakeUp2Interrupt = - INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback. - -static uint32_t sleepRemainingMs = 0ul; - -void wakeUp1(void) -{ - // Disable sleep. When an interrupt occurs after attachInterrupt, - // but before sleeping the CPU would not wake up. - // Ref: http://playground.arduino.cc/Learning/ArduinoSleepCode - sleep_disable(); - detachInterrupt(_wakeUp1Interrupt); - // First interrupt occurred will be reported only - if (INVALID_INTERRUPT_NUM == _wokeUpByInterrupt) { - _wokeUpByInterrupt = _wakeUp1Interrupt; - } -} -void wakeUp2(void) -{ - sleep_disable(); - detachInterrupt(_wakeUp2Interrupt); - // First interrupt occurred will be reported only - if (INVALID_INTERRUPT_NUM == _wokeUpByInterrupt) { - _wokeUpByInterrupt = _wakeUp2Interrupt; - } -} - -inline bool interruptWakeUp(void) -{ - return _wokeUpByInterrupt != INVALID_INTERRUPT_NUM; -} - -void clearPendingInterrupt(const uint8_t interrupt) -{ - EIFR = _BV(interrupt); -} - -// Watchdog Timer interrupt service routine. This routine is required -// to allow automatic WDIF and WDIE bit clearance in hardware. -ISR (WDT_vect) -{ -} - -void hwPowerDown(const uint8_t wdto) -{ - // Let serial prints finish (debug, log etc) -#ifndef MY_DISABLED_SERIAL - MY_SERIALDEVICE.flush(); -#endif - - // disable ADC for power saving - ADCSRA &= ~(1 << ADEN); - // save WDT settings - const uint8_t WDTsave = WDTCSR; - if (wdto != WDTO_SLEEP_FOREVER) { - wdt_enable(wdto); - // enable WDT interrupt before system reset - WDTCSR |= (1 << WDCE) | (1 << WDIE); - } else { - // if sleeping forever, disable WDT - wdt_disable(); - } - set_sleep_mode(SLEEP_MODE_PWR_DOWN); - cli(); - sleep_enable(); -#if defined(__AVR_ATmega328P__) - sleep_bod_disable(); -#endif - // Enable interrupts & sleep until WDT or ext. interrupt - sei(); - // Directly sleep CPU, to prevent race conditions! - // Ref: chapter 7.7 of ATMega328P datasheet - sleep_cpu(); - sleep_disable(); - // restore previous WDT settings - cli(); - wdt_reset(); - // enable WDT changes - WDTCSR |= (1 << WDCE) | (1 << WDE); - // restore saved WDT settings - WDTCSR = WDTsave; - sei(); - // enable ADC - ADCSRA |= (1 << ADEN); -} - -uint32_t hwInternalSleep(uint32_t ms) -{ - // Sleeping with watchdog only supports multiples of 16ms. - // Round up to next multiple of 16ms, to assure we sleep at least the - // requested amount of time. Sleep of 0ms will not sleep at all! - ms += 15u; - - while (!interruptWakeUp() && ms >= 16) { - for (uint8_t period = 9u; ; --period) { - const uint16_t comparatorMS = 1 << (period + 4); - if ( ms >= comparatorMS) { - hwPowerDown(period); // 8192ms => 9, 16ms => 0 - ms -= comparatorMS; - break; - } - } - } - if (interruptWakeUp()) { - return ms; - } - return 0ul; -} - -int8_t hwSleep(uint32_t ms) -{ - // Return what woke the mcu. - // Default: no interrupt triggered, timer wake up - int8_t ret = MY_WAKE_UP_BY_TIMER; - sleepRemainingMs = 0ul; - if (ms > 0u) { - // sleep for defined time - sleepRemainingMs = hwInternalSleep(ms); - } else { - // sleep until ext interrupt triggered - hwPowerDown(WDTO_SLEEP_FOREVER); - } - if (interruptWakeUp()) { - ret = static_cast(_wokeUpByInterrupt); - } - // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. - _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; - - return ret; -} - -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms) -{ - return hwSleep(interrupt, mode, INVALID_INTERRUPT_NUM, 0u, ms); -} - -int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, - uint32_t ms) -{ - // ATMega328P supports following modes to wake from sleep: LOW, CHANGE, RISING, FALLING - // Datasheet states only LOW can be used with INT0/1 to wake from sleep, which is incorrect. - // Ref: http://gammon.com.au/interrupts - - // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() - // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! - cli(); - // attach interrupts - _wakeUp1Interrupt = interrupt1; - _wakeUp2Interrupt = interrupt2; - - // Attach external interrupt handlers, and clear any pending interrupt flag - // to prevent waking immediately again. - // Ref: https://forum.arduino.cc/index.php?topic=59217.0 - if (interrupt1 != INVALID_INTERRUPT_NUM) { - clearPendingInterrupt(interrupt1); - attachInterrupt(interrupt1, wakeUp1, mode1); - } - if (interrupt2 != INVALID_INTERRUPT_NUM) { - clearPendingInterrupt(interrupt2); - attachInterrupt(interrupt2, wakeUp2, mode2); - } - - sleepRemainingMs = 0ul; - if (ms > 0u) { - // sleep for defined time - sleepRemainingMs = hwInternalSleep(ms); - } else { - // sleep until ext interrupt triggered - hwPowerDown(WDTO_SLEEP_FOREVER); - } - - // Assure any interrupts attached, will get detached when they did not occur. - if (interrupt1 != INVALID_INTERRUPT_NUM) { - detachInterrupt(interrupt1); - } - if (interrupt2 != INVALID_INTERRUPT_NUM) { - detachInterrupt(interrupt2); - } - - // Return what woke the mcu. - // Default: no interrupt triggered, timer wake up - int8_t ret = MY_WAKE_UP_BY_TIMER; - if (interruptWakeUp()) { - ret = static_cast(_wokeUpByInterrupt); - } - // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. - _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; - - return ret; -} - -uint32_t hwGetSleepRemaining(void) -{ - return sleepRemainingMs; -} - -inline void hwRandomNumberInit(void) -{ - // This function initializes the random number generator with a seed - // of 32 bits. This method is good enough to earn FIPS 140-2 conform - // random data. This should reach to generate 32 Bit for randomSeed(). - uint32_t seed = 0; - uint32_t timeout = millis() + 20; - - // Trigger floating effect of an unconnected pin - pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT_PULLUP); - pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT); - delay(10); - - // Generate 32 bits of datas - for (uint8_t i=0; i<32; i++) { - const int pinValue = analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN); - // Wait until the analog value has changed - while ((pinValue == analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)) && (timeout>=millis())) { - seed ^= (millis() << i); - // Check of data generation is slow - if (timeout<=millis()) { - // Trigger pin again - pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT_PULLUP); - pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT); - // Pause a short while - delay(seed % 10); - timeout = millis() + 20; - } - } - } - randomSeed(seed); -} - -bool hwUniqueID(unique_id_t *uniqueID) -{ - // padding - (void)memset(uniqueID, MY_HWID_PADDING_BYTE, sizeof(unique_id_t)); - // no unique ID for non-PB AVR, use HW specifics for diversification - *((uint8_t *)uniqueID) = SIGNATURE_2; - *((uint8_t *)uniqueID + 1) = SIGNATURE_1; - *((uint8_t *)uniqueID + 2) = SIGNATURE_0; - *((uint8_t *)uniqueID + 3) = OSCCAL; -#if defined(__AVR_ATmega328PB__) - // ATMEGA328PB specifics, has unique ID - for(uint8_t idx = 0; idx < 10; idx++) { - *((uint8_t *)uniqueID + 4 + idx) = boot_signature_byte_get(0xE + idx); - } - return true; // unique ID returned -#else - return false; // no unique ID returned -#endif -} - -uint16_t hwCPUVoltage(void) -{ - // Measure Vcc against 1.1V Vref -#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); -#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) - ADMUX = (_BV(MUX5) | _BV(MUX0)); -#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) - ADMUX = (_BV(MUX3) | _BV(MUX2)); -#else - ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); -#endif - // Vref settle - delay(70); - // Do conversion - ADCSRA |= _BV(ADSC); - while (bit_is_set(ADCSRA,ADSC)) {}; - // return Vcc in mV - return (1125300UL) / ADC; -} - -uint16_t hwCPUFrequency(void) -{ - cli(); - // save WDT & timer settings - const uint8_t WDTsave = WDTCSR; - const uint8_t TCCR1Asave = TCCR1A; - const uint8_t TCCR1Bsave = TCCR1B; - const uint8_t TCCR1Csave = TCCR1C; - // setup timer1 - TIFR1 = 0xFF; - TCNT1 = 0; - TCCR1A = 0; - TCCR1C = 0; - // set wdt - wdt_enable(WDTO_500MS); - // enable WDT interrupt mode => first timeout WDIF, 2nd timeout reset - WDTCSR |= (1 << WDIE); - wdt_reset(); - // start timer1 with 1024 prescaling - TCCR1B = _BV(CS12) | _BV(CS10); - // wait until wdt interrupt - while (bit_is_clear(WDTCSR,WDIF)) {}; - // stop timer - TCCR1B = 0; - // restore WDT settings - wdt_reset(); - WDTCSR |= (1 << WDCE) | (1 << WDE); - WDTCSR = WDTsave; - sei(); - const uint16_t result = TCNT1 * 2048UL / 100000UL; - // restore timer settings - TCCR1A = TCCR1Asave; - TCCR1B = TCCR1Bsave; - TCCR1C = TCCR1Csave; - // return frequency in 1/10MHz (accuracy +- 10%) - return result; -} - -int8_t hwCPUTemperature(void) -{ -#if defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328BP__) || defined(__AVR_ATmega32U4__) - // Set the internal reference and mux. - ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3)); - ADCSRA |= _BV(ADEN); // enable the ADC - delay(20); // wait for voltages to become stable. - ADCSRA |= _BV(ADSC); // Start the ADC - // Wait until conversion done - while (bit_is_set(ADCSRA, ADSC)); - // temperature is in degrees Celsius - return static_cast((ADCW - MY_AVR_TEMPERATURE_OFFSET) / MY_AVR_TEMPERATURE_GAIN); -#else - return -127; // not available -#endif -} - -uint16_t hwFreeMem(void) -{ - extern int __heap_start, *__brkval; - int v; - return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); -} diff --git a/lib/MySensors/hal/architecture/AVR/MyHwAVR.h b/lib/MySensors/hal/architecture/AVR/MyHwAVR.h deleted file mode 100644 index 52c0d8d8..00000000 --- a/lib/MySensors/hal/architecture/AVR/MyHwAVR.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyHwAVR_h -#define MyHwAVR_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Fast IO driver -#include "drivers/DigitalWriteFast/digitalWriteFast.h" - -// SOFTSPI -#ifdef MY_SOFTSPI -#include "hal/architecture/AVR/drivers/DigitalIO/DigitalIO.h" -#endif - -#ifdef __cplusplus -#include -#endif - -#define CRYPTO_LITTLE_ENDIAN - -#ifndef MY_SERIALDEVICE -#define MY_SERIALDEVICE Serial -#endif - -#ifndef MY_DEBUGDEVICE -#define MY_DEBUGDEVICE MY_SERIALDEVICE -#endif - -// AVR temperature calibration reference: http://ww1.microchip.com/downloads/en/AppNotes/Atmel-8108-Calibration-of-the-AVRs-Internal-Temperature-Reference_ApplicationNote_AVR122.pdf -#ifndef MY_AVR_TEMPERATURE_OFFSET -#define MY_AVR_TEMPERATURE_OFFSET (324.31f) -#endif - -#ifndef MY_AVR_TEMPERATURE_GAIN -#define MY_AVR_TEMPERATURE_GAIN (1.22f) -#endif - -// Define these as macros to save valuable space -#define hwDigitalWrite(__pin, __value) digitalWriteFast(__pin, __value) -#define hwDigitalRead(__pin) digitalReadFast(__pin) -#define hwPinMode(__pin, __value) pinModeFast(__pin, __value) - -bool hwInit(void); - -#define hwWatchdogReset() wdt_reset() -#define hwReboot() wdt_enable(WDTO_15MS); while (1) -#define hwMillis() millis() -#define hwReadConfig(__pos) eeprom_read_byte((const uint8_t *)__pos) -#define hwWriteConfig(__pos, __val) eeprom_update_byte((uint8_t *)__pos, (uint8_t)__val) -#define hwReadConfigBlock(__buf, __pos, __length) eeprom_read_block((void *)__buf, (const void *)__pos, (uint32_t)__length) -#define hwWriteConfigBlock(__buf, __pos, __length) eeprom_update_block((const void *)__buf, (void *)__pos, (uint32_t)__length) - -inline void hwRandomNumberInit(void); -uint32_t hwInternalSleep(uint32_t ms); - -#if defined(MY_SOFTSPI) -SoftSPI hwSPI; //!< hwSPI -#else -#define hwSPI SPI //!< hwSPI -#endif - -#ifndef DOXYGEN -#define MY_CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE) -#endif /* DOXYGEN */ - -#endif diff --git a/lib/MySensors/hal/architecture/AVR/MyMainAVR.cpp b/lib/MySensors/hal/architecture/AVR/MyMainAVR.cpp deleted file mode 100644 index dd02675f..00000000 --- a/lib/MySensors/hal/architecture/AVR/MyMainAVR.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -// Initialize library and handle sketch functions like we want to - -int main(void) -{ - init(); -#if defined(USBCON) - USBDevice.attach(); -#endif - _begin(); // Startup MySensors library - for(;;) { - _process(); // Process incoming data - if (loop) { - loop(); // Call sketch loop - } - if (serialEventRun) { - serialEventRun(); - } - } - return 0; -} diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/DigitalIO.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/DigitalIO.h deleted file mode 100644 index 4b4ca77e..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/DigitalIO.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -/** - * @file - * @brief Fast Digital I/O functions - * - */ -#ifndef DigitalIO_h -#define DigitalIO_h 1 -//------------------------------------------------------------------------------ -/** DigitalPin version YYYYMMDD */ -#define DIGITAL_IO_VERSION 20151127 -//------------------------------------------------------------------------------ -#include "DigitalPin.h" -#include "I2cConstants.h" -#include "PinIO.h" -#include "SoftI2cMaster.h" -#include "SoftSPI.h" -#endif // DigitalIO_h diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/DigitalPin.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/DigitalPin.h deleted file mode 100644 index cf546752..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/DigitalPin.h +++ /dev/null @@ -1,416 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -/** - * @file - * @brief Fast Digital Pin functions - * - * @defgroup digitalPin Fast Pin I/O - * @details Fast Digital I/O functions and template class. - * @{ - */ -#ifndef DigitalPin_h -#define DigitalPin_h -#if defined(__AVR__) || defined(DOXYGEN) -#include -/** GpioPinMap type */ -struct GpioPinMap_t { - volatile uint8_t* pin; /**< address of PIN for this pin */ - volatile uint8_t* ddr; /**< address of DDR for this pin */ - volatile uint8_t* port; /**< address of PORT for this pin */ - uint8_t mask; /**< bit mask for this pin */ -}; - -/** Initializer macro. */ -#define GPIO_PIN(reg, bit) {&PIN##reg, &DDR##reg, &PORT##reg, 1 << bit} - -// Include pin map for current board. -#include "boards/GpioPinMap.h" -//------------------------------------------------------------------------------ -/** generate bad pin number error */ -void badPinNumber(void) -__attribute__((error("Pin number is too large or not a constant"))); -//------------------------------------------------------------------------------ -/** Check for valid pin number - * @param[in] pin Number of pin to be checked. - */ -static inline __attribute__((always_inline)) -void badPinCheck(uint8_t pin) -{ - if (!__builtin_constant_p(pin) || pin >= NUM_DIGITAL_PINS) { - badPinNumber(); - } -} -//------------------------------------------------------------------------------ -/** DDR register address - * @param[in] pin Arduino pin number - * @return register address - */ -static inline __attribute__((always_inline)) -volatile uint8_t* ddrReg(uint8_t pin) -{ - badPinCheck(pin); - return GpioPinMap[pin].ddr; -} -//------------------------------------------------------------------------------ -/** Bit mask for pin - * @param[in] pin Arduino pin number - * @return mask - */ -static inline __attribute__((always_inline)) -uint8_t pinMask(uint8_t pin) -{ - badPinCheck(pin); - return GpioPinMap[pin].mask; -} -//------------------------------------------------------------------------------ -/** PIN register address - * @param[in] pin Arduino pin number - * @return register address - */ -static inline __attribute__((always_inline)) -volatile uint8_t* pinReg(uint8_t pin) -{ - badPinCheck(pin); - return GpioPinMap[pin].pin; -} -//------------------------------------------------------------------------------ -/** PORT register address - * @param[in] pin Arduino pin number - * @return register address - */ -static inline __attribute__((always_inline)) -volatile uint8_t* portReg(uint8_t pin) -{ - badPinCheck(pin); - return GpioPinMap[pin].port; -} -//------------------------------------------------------------------------------ -/** Fast write helper. - * @param[in] address I/O register address - * @param[in] mask bit mask for pin - * @param[in] level value for bit - */ -static inline __attribute__((always_inline)) -void fastBitWriteSafe(volatile uint8_t* address, uint8_t mask, bool level) -{ - uint8_t s; - if (address > reinterpret_cast(0X3F)) { - s = SREG; - cli(); - } - if (level) { - *address |= mask; - } else { - *address &= ~mask; - } - if (address > reinterpret_cast(0X3F)) { - SREG = s; - } -} -//------------------------------------------------------------------------------ -/** Read pin value. - * @param[in] pin Arduino pin number - * @return value read - */ -static inline __attribute__((always_inline)) -bool fastDigitalRead(uint8_t pin) -{ - return *pinReg(pin) & pinMask(pin); -} -//------------------------------------------------------------------------------ -/** Toggle a pin. - * @param[in] pin Arduino pin number - * - * If the pin is in output mode toggle the pin level. - * If the pin is in input mode toggle the state of the 20K pullup. - */ -static inline __attribute__((always_inline)) -void fastDigitalToggle(uint8_t pin) -{ - if (pinReg(pin) > reinterpret_cast(0X3F)) { - // must write bit to high address port - *pinReg(pin) = pinMask(pin); - } else { - // will compile to sbi and PIN register will not be read. - *pinReg(pin) |= pinMask(pin); - } -} -//------------------------------------------------------------------------------ -/** Set pin value. - * @param[in] pin Arduino pin number - * @param[in] level value to write - */ -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, bool level) -{ - fastBitWriteSafe(portReg(pin), pinMask(pin), level); -} -//------------------------------------------------------------------------------ -/** Write the DDR register. - * @param[in] pin Arduino pin number - * @param[in] level value to write - */ -static inline __attribute__((always_inline)) -void fastDdrWrite(uint8_t pin, bool level) -{ - fastBitWriteSafe(ddrReg(pin), pinMask(pin), level); -} -//------------------------------------------------------------------------------ -/** Set pin mode. - * @param[in] pin Arduino pin number - * @param[in] mode INPUT, OUTPUT, or INPUT_PULLUP. - * - * The internal pullup resistors will be enabled if mode is INPUT_PULLUP - * and disabled if the mode is INPUT. - */ -static inline __attribute__((always_inline)) -void fastPinMode(uint8_t pin, uint8_t mode) -{ - fastDdrWrite(pin, mode == OUTPUT); - if (mode != OUTPUT) { - fastDigitalWrite(pin, mode == INPUT_PULLUP); - } -} -#else // defined(__AVR__) -#if defined(CORE_TEENSY) -//------------------------------------------------------------------------------ -/** read pin value - * @param[in] pin Arduino pin number - * @return value read - */ -static inline __attribute__((always_inline)) -bool fastDigitalRead(uint8_t pin) -{ - return *portInputRegister(pin); -} -//------------------------------------------------------------------------------ -/** Set pin value - * @param[in] pin Arduino pin number - * @param[in] level value to write - */ -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, bool value) -{ - if (value) { - *portSetRegister(pin) = 1; - } else { - *portClearRegister(pin) = 1; - } -} -#elif defined(__SAM3X8E__) || defined(__SAM3X8H__) -//------------------------------------------------------------------------------ -/** read pin value - * @param[in] pin Arduino pin number - * @return value read - */ -static inline __attribute__((always_inline)) -bool fastDigitalRead(uint8_t pin) -{ - return g_APinDescription[pin].pPort->PIO_PDSR & g_APinDescription[pin].ulPin; -} -//------------------------------------------------------------------------------ -/** Set pin value - * @param[in] pin Arduino pin number - * @param[in] level value to write - */ -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, bool value) -{ - if (value) { - g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin; - } else { - g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin; - } -} -#elif defined(ESP8266) -//------------------------------------------------------------------------------ -/** Set pin value - * @param[in] pin Arduino pin number - * @param[in] val value to write - */ -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, uint8_t val) -{ - if (pin < 16) { - if (val) { - GPOS = (1 << pin); - } else { - GPOC = (1 << pin); - } - } else if (pin == 16) { - if (val) { - GP16O |= 1; - } else { - GP16O &= ~1; - } - } -} -//------------------------------------------------------------------------------ -/** Read pin value - * @param[in] pin Arduino pin number - * @return value read - */ -static inline __attribute__((always_inline)) -bool fastDigitalRead(uint8_t pin) -{ - if (pin < 16) { - return GPIP(pin); - } else if (pin == 16) { - return GP16I & 0x01; - } - return 0; -} -#else // CORE_TEENSY -//------------------------------------------------------------------------------ -inline void fastDigitalWrite(uint8_t pin, bool value) -{ - digitalWrite(pin, value); -} -//------------------------------------------------------------------------------ -inline bool fastDigitalRead(uint8_t pin) -{ - return digitalRead(pin); -} -#endif // CORE_TEENSY -//------------------------------------------------------------------------------ -inline void fastDigitalToggle(uint8_t pin) -{ - fastDigitalWrite(pin, !fastDigitalRead(pin)); -} -//------------------------------------------------------------------------------ -inline void fastPinMode(uint8_t pin, uint8_t mode) -{ - pinMode(pin, mode); -} -#endif // __AVR__ -//------------------------------------------------------------------------------ -/** set pin configuration - * @param[in] pin Arduino pin number - * @param[in] mode mode INPUT or OUTPUT. - * @param[in] level If mode is output, set level high/low. - * If mode is input, enable or disable the pin's 20K pullup. - */ -#define fastPinConfig(pin, mode, level)\ - {fastPinMode(pin, mode); fastDigitalWrite(pin, level);} -//============================================================================== -/** - * @class DigitalPin - * @brief Fast digital port I/O - */ -template -class DigitalPin -{ -public: - //---------------------------------------------------------------------------- - /** Constructor */ - DigitalPin() {} - //---------------------------------------------------------------------------- - /** Asignment operator. - * @param[in] value If true set the pin's level high else set the - * pin's level low. - * - * @return This DigitalPin instance. - */ - inline DigitalPin & operator = (bool value) __attribute__((always_inline)) - { - write(value); - return *this; - } - //---------------------------------------------------------------------------- - /** Parenthesis operator. - * @return Pin's level - */ - inline operator bool () const __attribute__((always_inline)) - { - return read(); - } - //---------------------------------------------------------------------------- - /** Set pin configuration. - * @param[in] mode: INPUT or OUTPUT. - * @param[in] level If mode is OUTPUT, set level high/low. - * If mode is INPUT, enable or disable the pin's 20K pullup. - */ - inline __attribute__((always_inline)) - void config(uint8_t mode, bool level) - { - fastPinConfig(PinNumber, mode, level); - } - //---------------------------------------------------------------------------- - /** - * Set pin level high if output mode or enable 20K pullup if input mode. - */ - inline __attribute__((always_inline)) - void high() - { - write(true); - } - //---------------------------------------------------------------------------- - /** - * Set pin level low if output mode or disable 20K pullup if input mode. - */ - inline __attribute__((always_inline)) - void low() - { - write(false); - } - //---------------------------------------------------------------------------- - /** - * Set pin mode. - * @param[in] mode: INPUT, OUTPUT, or INPUT_PULLUP. - * - * The internal pullup resistors will be enabled if mode is INPUT_PULLUP - * and disabled if the mode is INPUT. - */ - inline __attribute__((always_inline)) - void mode(uint8_t mode) - { - fastPinMode(PinNumber, mode); - } - //---------------------------------------------------------------------------- - /** @return Pin's level. */ - inline __attribute__((always_inline)) - bool read() const - { - return fastDigitalRead(PinNumber); - } - //---------------------------------------------------------------------------- - /** Toggle a pin. - * - * If the pin is in output mode toggle the pin's level. - * If the pin is in input mode toggle the state of the 20K pullup. - */ - inline __attribute__((always_inline)) - void toggle() - { - fastDigitalToggle(PinNumber); - } - //---------------------------------------------------------------------------- - /** Write the pin's level. - * @param[in] value If true set the pin's level high else set the - * pin's level low. - */ - inline __attribute__((always_inline)) - void write(bool value) - { - fastDigitalWrite(PinNumber, value); - } -}; -#endif // DigitalPin_h -/** @} */ diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/I2cConstants.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/I2cConstants.h deleted file mode 100644 index f2d07671..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/I2cConstants.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Arduino I2C Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino I2C Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino I2C Library. If not, see - * . - */ -/** - * @file I2cConstants.h - * @brief Two Wire Interface constants. - * - * @defgroup twoWire I2C constants - * @details Two Wire Interface library. - * @{ - */ -#ifndef I2cConstants_h -#define I2cConstants_h -#include - -/** Option argument for transfer() of transferContinue() to continue a - an I2C operation. */ -const uint8_t I2C_CONTINUE = 0; - -/** Option argument for transfer() of transferContinue() to end a - transfer with a STOP condition */ -const uint8_t I2C_STOP = 1; - -/** Option argument for transfer() of transferContinue() to end a - transfer with a repeated START condition */ -const uint8_t I2C_REP_START = 2; - -/** Set I2C bus speed to 100 kHz. Used by TwiMaster class. */ -const uint8_t I2C_100KHZ = 0; - -/** Set I2C bus speed to 400 kHz. Used by TwiMaster class. */ -const uint8_t I2C_400KHZ = 1; - -/** Bit to OR with address for a read operation. */ -const uint8_t I2C_READ = 1; - -/** Bit to OR with address for write operation. */ -const uint8_t I2C_WRITE = 0; - -/** Disable internal pull-ups on SDA and SCL. Used by TwiMaster class. */ -const uint8_t I2C_NO_PULLUPS = 0; - -/** Enable internal pull-ups on SDA and SCL. Used by TwiMaster class. */ -const uint8_t I2C_INTERNAL_PULLUPS = 1; -#endif // I2cConstants_h -/** @} */ diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/PinIO.cpp b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/PinIO.cpp deleted file mode 100644 index b3403426..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/PinIO.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -/** - * @file - * @brief Digital AVR port I/O with runtime pin number. - * - * @defgroup runtimeDigital Runtime Pin I/O - * @details Two Wire Interface library. - * @{ - */ -#if defined(__AVR__) || defined(DOXYGEN) // AVR only -#include "PinIO.h" -#include -#include -//============================================================================== -/** Constructor - * @param[in] pin Pin assigned to this object. - */ -PinIO::PinIO(uint8_t pin) -{ - begin(pin); -} -//------------------------------------------------------------------------------ -/** Initialize pin bit mask and port address. - * @param[in] pin Arduino board pin number. - * @return true for success or false if invalid pin number. - */ -bool PinIO::begin(uint8_t pin) -{ - if (pin >= NUM_DIGITAL_PINS) { - return false; - } - uint8_t port = digitalPinToPort(pin); - pinReg_ = portInputRegister(port); - bit_ = digitalPinToBitMask(pin); - mask_ = ~bit_; - portReg_ = pinReg_ + 2; - return true; -} -//------------------------------------------------------------------------------ -/** Configure the pin. - * - * @param[in] mode: INPUT or OUTPUT. - * @param[in] level If mode is OUTPUT, set level high/low. - * If mode is INPUT, enable or disable the pin's 20K pullup. - * - * This function may be used with interrupts enabled or disabled. - * The previous interrupt state will be restored. - */ -void PinIO::config(uint8_t mode, bool level) -{ - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - modeI(mode); - writeI(level); - } -} -#endif // __AVR__ -/** @} */ diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/PinIO.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/PinIO.h deleted file mode 100644 index 2bb218e2..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/PinIO.h +++ /dev/null @@ -1,194 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -/** - * @file - * @brief Digital AVR port I/O with runtime pin number. - * - * @defgroup runtimeDigital Runtime Pin I/O - * @details Two Wire Interface library. - * @{ - */ -#ifndef PinIO_h -#define PinIO_h -#if defined(__AVR__) || defined(DOXYGEN) // AVR only -#include -#include -#include -//------------------------------------------------------------------------------ -/** - * @class PinIO - * @brief AVR port I/O with runtime pin numbers. - */ -class PinIO -{ -public: - /** Create a PinIO object with no assigned pin. */ - // cppcheck-suppress uninitMemberVar - PinIO() : bit_(0), mask_(0XFF) {} - explicit PinIO(uint8_t pin); - bool begin(uint8_t pin); - void config(uint8_t mode, bool data); - //---------------------------------------------------------------------------- - /** @return Pin's level */ - inline __attribute__((always_inline)) - bool read() - { - return *pinReg_ & bit_; - } - //---------------------------------------------------------------------------- - /** toggle a pin - * - * If the pin is in output mode toggle the pin's level. - * If the pin is in input mode toggle the state of the 20K pullup. - */ - inline __attribute__((always_inline)) - void toggle() - { - *pinReg_ = bit_; - } - //============================================================================ - /** - * Set pin high if output mode or enable 20K pullup if input mode. - * - * This function must be called with interrupts disabled. - * This function will not change the interrupt state. - */ - inline __attribute__((always_inline)) - void highI() - { - writeI(1); - } - /** - * Set pin low if output mode or disable 20K pullup if input mode. - * - * This function must be called with interrupts disabled. - * This function will not change the interrupt state. - */ - inline __attribute__((always_inline)) - void lowI() - { - writeI(0); - } - /** Set pin mode. - * - * @param[in] mode: INPUT, OUTPUT, or INPUT_PULLUP. - * - * The internal pullup resistors will be enabled if mode is INPUT_PULLUP - * and disabled if the mode is INPUT. - * - * This function must be called with interrupts disabled. - * This function will not change the interrupt state. - */ - inline __attribute__((always_inline)) - void modeI(uint8_t mode) - { - volatile uint8_t* ddrReg = pinReg_ + 1; - *ddrReg = mode == OUTPUT ? *ddrReg | bit_ : *ddrReg & mask_; - if (mode != OUTPUT) { - writeI(mode == INPUT_PULLUP); - } - } - - /** Write pin. - * - * @param[in] level If output mode set pin high if true else low. - * If input mode enable 20K pullup if true else disable pullup. - * - * This function must be called with interrupts disabled. - * This function will not change the interrupt state. - */ - inline __attribute__((always_inline)) - void writeI(bool level) - { - *portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_; - } - //============================================================================ - /** - * Set pin level high if output mode or enable 20K pullup if input mode. - * - * This function will enable interrupts. This function should not be - * called in an ISR or where interrupts are disabled. - */ - inline __attribute__((always_inline)) - void high() - { - ATOMIC_BLOCK(ATOMIC_FORCEON) { - highI(); - } - } - - /** - * Set pin level low if output mode or disable 20K pullup if input mode. - * - * This function will enable interrupts. This function should not be - * called in an ISR or where interrupts are disabled. - */ - inline __attribute__((always_inline)) - void low() - { - ATOMIC_BLOCK(ATOMIC_FORCEON) { - lowI(); - } - } - - /** - * Set pin mode. - * - * @param[in] mode: INPUT, OUTPUT, or INPUT_PULLUP. - * - * The internal pullup resistors will be enabled if mode is INPUT_PULLUP - * and disabled if the mode is INPUT. - * - * This function will enable interrupts. This function should not be - * called in an ISR or where interrupts are disabled. - */ - inline __attribute__((always_inline)) - void mode(uint8_t mode) - { - ATOMIC_BLOCK(ATOMIC_FORCEON) { - modeI(mode); - } - } - - /** Write pin. - * - * @param[in] level If output mode set pin high if true else low. - * If input mode enable 20K pullup if true else disable pullup. - * - * This function will enable interrupts. This function should not be - * called in an ISR or where interrupts are disabled. - */ - inline __attribute__((always_inline)) - void write(bool level) - { - ATOMIC_BLOCK(ATOMIC_FORCEON) { - writeI(level); - } - } - //---------------------------------------------------------------------------- -private: - uint8_t bit_; - uint8_t mask_; - volatile uint8_t* pinReg_; - volatile uint8_t* portReg_; -}; -#endif // __AVR__ -#endif // PinIO_h -/** @} */ diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftI2cMaster.cpp b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftI2cMaster.cpp deleted file mode 100644 index e3c6d372..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftI2cMaster.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -#if defined(__AVR__) || defined(DOXYGEN) // AVR only -/** - * @file - * @brief AVR Software I2C library - * - * @defgroup softI2C Software I2C - * @details Software Two Wire Interface library. - * @{ - */ -#include "SoftI2cMaster.h" -//------------------------------------------------------------------------------ -/** - * Start an I2C transfer with possible continuation. - * - * @param[in] addrRW I2C slave address plus R/W bit. - * The I2C slave address is in the high seven bits - * and is ORed with on of the following: - * - I2C_READ for a read transfer. - * - I2C_WRITE for a write transfer. - * . - * @param[in,out] buf Source or destination for transfer. - * @param[in] nbytes Number of bytes to transfer (may be zero). - * @param[in] option Option for ending the transfer, one of: - * - I2C_STOP end the transfer with an I2C stop - * condition. - * - I2C_REP_START end the transfer with an I2C - * repeated start condition. - * - I2C_CONTINUE allow additional transferContinue() - * calls. - * . - * @return true for success else false. - */ -bool I2cMasterBase::transfer(uint8_t addrRW, - void *buf, size_t nbytes, uint8_t option) -{ - if (_state != STATE_REP_START) { - start(); - } - if (!write(addrRW)) { - _state = (addrRW & I2C_READ) ? STATE_RX_ADDR_NACK : STATE_TX_ADDR_NACK; - return false; - } - _state = (addrRW & I2C_READ) ? STATE_RX_DATA : STATE_TX_DATA; - return transferContinue(buf, nbytes, option); -} -//------------------------------------------------------------------------------ -/** - * Continue an I2C transfer. - * - * @param[in,out] buf Source or destination for transfer. - * @param[in] nbytes Number of bytes to transfer (may be zero). - * @param[in] option Option for ending the transfer, one of: - * - I2C_STOP end the transfer with an I2C stop - * condition. - * - I2C_REP_START end the transfer with an I2C - * repeated start condition. - * - I2C_CONTINUE allow additional transferContinue() - * calls. - * . - * @return true for success else false. - */ -bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) -{ - uint8_t* p = reinterpret_cast(buf); - if (_state == STATE_RX_DATA) { - for (size_t i = 0; i < nbytes; i++) { - p[i] = read(i == (nbytes - 1) && option != I2C_CONTINUE); - } - } else if (_state == STATE_TX_DATA) { - for (size_t i = 0; i < nbytes; i++) { - if (!write(p[i])) { - _state = STATE_TX_DATA_NACK; - return false; - } - } - } else { - return false; - } - if (option == I2C_STOP) { - stop(); - _state = STATE_STOP; - } else if (option == I2C_REP_START) { - start(); - _state = STATE_STOP; - } - return true; -} -//============================================================================== -// WARNING don't change SoftI2cMaster unless you verify the change with a scope -//------------------------------------------------------------------------------ -/** - * Constructor, initialize SCL/SDA pins and set the bus high. - * - * @param[in] sdaPin The software SDA pin number. - * - * @param[in] sclPin The software SCL pin number. - */ -SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) -{ - begin(sclPin, sdaPin); -} -//------------------------------------------------------------------------------ -/** - * Initialize SCL/SDA pins and set the bus high. - * - * @param[in] sdaPin The software SDA pin number. - * - * @param[in] sclPin The software SCL pin number. - */ -void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) -{ - uint8_t port; - - // Get bit mask and address of scl registers. - _sclBit = digitalPinToBitMask(sclPin); - port = digitalPinToPort(sclPin); - _sclDDR = portModeRegister(port); - volatile uint8_t* sclOutReg = portOutputRegister(port); - - // Get bit mask and address of sda registers. - _sdaBit = digitalPinToBitMask(sdaPin); - port = digitalPinToPort(sdaPin); - _sdaDDR = portModeRegister(port); - _sdaInReg = portInputRegister(port); - volatile uint8_t* sdaOutReg = portOutputRegister(port); - - // Clear PORT bit for scl and sda. - uint8_t s = SREG; - noInterrupts(); - *sclOutReg &= ~_sclBit; - *sdaOutReg &= ~_sdaBit; - SREG = s; - - // Set scl and sda high. - writeScl(HIGH); - writeSda(HIGH); -} -//------------------------------------------------------------------------------ -/* Read a byte and send ACK if more reads follow else NACK to terminate read. - * - * @param[in] last Set true to terminate the read else false. - * - * @return The byte read from the I2C bus. - */ -uint8_t SoftI2cMaster::read(uint8_t last) -{ - uint8_t b = 0; - - // Set sda to high Z mode for read. - writeSda(HIGH); - // Read a byte. - for (uint8_t i = 0; i < 8; i++) { - // Don't change this loop unless you verify the change with a scope. - b <<= 1; - sclDelay(16); - writeScl(HIGH); - sclDelay(12); - if (readSda()) { - b |= 1; - } - writeScl(LOW); - } - // send ACK or NACK - writeSda(last); - sclDelay(12); - writeScl(HIGH); - sclDelay(18); - writeScl(LOW); - writeSda(LOW); - return b; -} -//------------------------------------------------------------------------------ -/* Issue a start condition. */ -void SoftI2cMaster::start() -{ - if (!readSda()) { - writeSda(HIGH); - writeScl(HIGH); - sclDelay(20); - } - writeSda(LOW); - sclDelay(20); - writeScl(LOW); -} -//------------------------------------------------------------------------------ -/* Issue a stop condition. */ -void SoftI2cMaster::stop(void) -{ - writeSda(LOW); - sclDelay(20); - writeScl(HIGH); - sclDelay(20); - writeSda(HIGH); - sclDelay(20); -} -//------------------------------------------------------------------------------ -/* - * Write a byte. - * - * @param[in] data The byte to send. - * - * @return The value true, 1, if the slave returned an ACK or false for NACK. - */ -bool SoftI2cMaster::write(uint8_t data) -{ - // write byte - for (uint8_t m = 0X80; m != 0; m >>= 1) { - // don't change this loop unless you verify the change with a scope - writeSda(m & data); - sclDelay(8); - writeScl(HIGH); - sclDelay(18); - writeScl(LOW); - } - sclDelay(8); - // Go to sda high Z mode for input. - writeSda(HIGH); - writeScl(HIGH); - sclDelay(16); - - // Get ACK or NACK. - uint8_t rtn = readSda(); - - // pull scl low. - writeScl(LOW); - - // Pull sda low. - writeSda(LOW); - return rtn == 0; -} -#endif // __AVR__ -/** @} */ - diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftI2cMaster.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftI2cMaster.h deleted file mode 100644 index 48045927..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftI2cMaster.h +++ /dev/null @@ -1,314 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -#ifndef SOFT_I2C_MASTER_H -#define SOFT_I2C_MASTER_H -/** - * @file - * @brief AVR Software I2C library - * - * @defgroup softI2C Software I2C - * @details Software Two Wire Interface library. - * @{ - */ -#if defined(__AVR__) || defined(DOXYGEN) // AVR only -#include -#include -#include "DigitalPin.h" -#include "I2cConstants.h" -//------------------------------------------------------------------------------ -// State codes. - -/** Stop condition transmitted. */ -const uint8_t STATE_STOP = 0; - -/** Repeated start condition transmitted. */ -const uint8_t STATE_REP_START = 1; - -/** Read data transfer active. */ -const uint8_t STATE_RX_DATA = 2; - -/** Write data transfer active. */ -const uint8_t STATE_TX_DATA = 3; - -/** Slave address plus read bit transmitted, NACK received. */ -const uint8_t STATE_RX_ADDR_NACK = 4; - -/** Slave address plus write bit transmitted, NACK received. */ -const uint8_t STATE_TX_ADDR_NACK = 5; -/** Data byte transmitted, NACK received. */ -const uint8_t STATE_TX_DATA_NACK = 6; -//============================================================================== -/** - * @class I2cMasterBase - * @brief Base class for FastI2cMaster, SoftI2cMaster - */ -class I2cMasterBase -{ -public: - I2cMasterBase() : _state(STATE_STOP) {} - /** Read a byte - * - * @note This function should only be used by experts. Data should be - * accessed by calling transfer() and transferContinue() - * - * @param[in] last send a NACK to terminate read if last is true else - * send an ACK to continue the read. - * - * @return byte read from I2C bus - */ - virtual uint8_t read(uint8_t last) = 0; - - /** Issue a start condition - * - * @note This function should only be used by experts. Data should be - * accessed by calling transfer() and transferContinue() - */ - virtual void start() = 0; - /** Issue a stop condition. - * - * @note This function should only be used by experts. Data should be - * accessed by calling transfer() and transferContinue() - */ - virtual void stop() = 0; - - bool transfer(uint8_t addressRW, void *buf, - size_t nbyte, uint8_t option = I2C_STOP); - - bool transferContinue(void *buf, size_t nbyte, uint8_t option = I2C_STOP); - /** Write a byte - * - * @note This function should only be used by experts. Data should be - * accessed by calling transfer() and transferContinue() - * - * @param[in] data byte to write - * @return true for ACK or false for NACK */ - virtual bool write(uint8_t data) = 0; - -private: - uint8_t _state; -}; -//============================================================================== -/** - * @class SoftI2cMaster - * @brief AVR Software I2C master class - */ -class SoftI2cMaster : public I2cMasterBase -{ -public: - SoftI2cMaster() {} - SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin); - void begin(uint8_t sclPin, uint8_t sdaPin); - uint8_t read(uint8_t last); - void start(); - void stop(void); - bool write(uint8_t b); - -private: - uint8_t _sclBit; - uint8_t _sdaBit; - volatile uint8_t* _sclDDR; - volatile uint8_t* _sdaDDR; - volatile uint8_t* _sdaInReg; - //---------------------------------------------------------------------------- - bool readSda() - { - return *_sdaInReg & _sdaBit; - } - //---------------------------------------------------------------------------- - void sclDelay(uint8_t n) - { - _delay_loop_1(n); - } - //---------------------------------------------------------------------------- - void writeScl(bool value) - { - uint8_t s = SREG; - noInterrupts(); - if (value == LOW) { - // Pull scl low. - *_sclDDR |= _sclBit; - } else { - // Put scl in high Z input mode. - *_sclDDR &= ~_sclBit; - } - SREG = s; - } - //---------------------------------------------------------------------------- - void writeSda(bool value) - { - uint8_t s = SREG; - noInterrupts(); - if (value == LOW) { - // Pull sda low. - *_sdaDDR |= _sdaBit; - } else { - // Put sda in high Z input mode. - *_sdaDDR &= ~_sdaBit; - } - SREG = s; - } -}; -//============================================================================== -// Template based fast software I2C -//------------------------------------------------------------------------------ -/** - * @class FastI2cMaster - * @brief AVR Fast software I2C master class. - */ -template -class FastI2cMaster : public I2cMasterBase -{ -public: - //---------------------------------------------------------------------------- - FastI2cMaster() - { - begin(); - } - //---------------------------------------------------------------------------- - /** Initialize I2C bus pins. */ - void begin() - { - fastDigitalWrite(sclPin, LOW); - fastDigitalWrite(sdaPin, LOW); - - sclWrite(HIGH); - sdaWrite(HIGH); - } - //---------------------------------------------------------------------------- - uint8_t read(uint8_t last) - { - uint8_t data = 0; - sdaWrite(HIGH); - - readBit(7, &data); - readBit(6, &data); - readBit(5, &data); - readBit(4, &data); - readBit(3, &data); - readBit(2, &data); - readBit(1, &data); - readBit(0, &data); - - // send ACK or NACK - sdaWrite(last); - sclDelay(4); - sclWrite(HIGH); - sclDelay(6); - sclWrite(LOW); - sdaWrite(LOW); - return data; - } - //---------------------------------------------------------------------------- - void start() - { - if (!fastDigitalRead(sdaPin)) { - // It's a repeat start. - sdaWrite(HIGH); - sclDelay(8); - sclWrite(HIGH); - sclDelay(8); - } - sdaWrite(LOW); - sclDelay(8); - sclWrite(LOW); - sclDelay(8); - } - //---------------------------------------------------------------------------- - void stop(void) - { - sdaWrite(LOW); - sclDelay(8); - sclWrite(HIGH); - sclDelay(8); - sdaWrite(HIGH); - sclDelay(8); - } - //---------------------------------------------------------------------------- - bool write(uint8_t data) - { - // write byte - writeBit(7, data); - writeBit(6, data); - writeBit(5, data); - writeBit(4, data); - writeBit(3, data); - writeBit(2, data); - writeBit(1, data); - writeBit(0, data); - - // get ACK or NACK - sdaWrite(HIGH); - - sclWrite(HIGH); - sclDelay(5); - bool rtn = fastDigitalRead(sdaPin); - sclWrite(LOW); - sdaWrite(LOW); - return rtn == 0; - } - -private: - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void sclWrite(bool value) - { - fastDdrWrite(sclPin, !value); - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void sdaWrite(bool value) - { - fastDdrWrite(sdaPin, !value); - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void readBit(uint8_t bit, uint8_t* data) - { - sclWrite(HIGH); - sclDelay(5); - if (fastDigitalRead(sdaPin)) { - *data |= 1 << bit; - } - sclWrite(LOW); - if (bit) { - sclDelay(6); - } - } - //---------------------------------------------------------------------------- - void sclDelay(uint8_t n) - { - _delay_loop_1(n); - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void writeBit(uint8_t bit, uint8_t data) - { - uint8_t mask = 1 << bit; - sdaWrite(data & mask); - sclWrite(HIGH); - sclDelay(5); - sclWrite(LOW); - sclDelay(5); - } -}; -#endif // __AVR__ -#endif // SOFT_I2C_MASTER_H -/** @} */ - diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftSPI.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftSPI.h deleted file mode 100644 index 1cccc9d0..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/SoftSPI.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -/** - * @file - * @brief Software SPI. - * - * @defgroup softSPI Software SPI - * @details Software SPI Template Class. - * @{ - */ - -#ifndef SoftSPI_h -#define SoftSPI_h -#include "DigitalPin.h" -//------------------------------------------------------------------------------ -/** Nop for timing. */ -#define nop asm volatile ("nop\n\t") -//------------------------------------------------------------------------------ -/** Pin Mode for MISO is input.*/ -#define MISO_MODE INPUT -/** Pullups disabled for MISO are disabled. */ -#define MISO_LEVEL false -/** Pin Mode for MOSI is output.*/ -#define MOSI_MODE OUTPUT -/** Pin Mode for SCK is output. */ -#define SCK_MODE OUTPUT -//------------------------------------------------------------------------------ -/** - * @class SoftSPI - * @brief Fast software SPI. - */ -template -class SoftSPI -{ -public: - //---------------------------------------------------------------------------- - /** Initialize SoftSPI pins. */ - void begin() - { - fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL); - fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode)); - fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode)); - } - //---------------------------------------------------------------------------- - /** Soft SPI receive byte. - * @return Data byte received. - */ - inline __attribute__((always_inline)) - uint8_t receive() - { - uint8_t data = 0; - receiveBit(7, &data); - receiveBit(6, &data); - receiveBit(5, &data); - receiveBit(4, &data); - receiveBit(3, &data); - receiveBit(2, &data); - receiveBit(1, &data); - receiveBit(0, &data); - return data; - } - //---------------------------------------------------------------------------- - /** Soft SPI send byte. - * @param[in] data Data byte to send. - */ - inline __attribute__((always_inline)) - void send(uint8_t data) - { - sendBit(7, data); - sendBit(6, data); - sendBit(5, data); - sendBit(4, data); - sendBit(3, data); - sendBit(2, data); - sendBit(1, data); - sendBit(0, data); - } - //---------------------------------------------------------------------------- - /** Soft SPI transfer byte. - * @param[in] txData Data byte to send. - * @return Data byte received. - */ - inline __attribute__((always_inline)) - uint8_t transfer(uint8_t txData) - { - uint8_t rxData = 0; - transferBit(7, &rxData, txData); - transferBit(6, &rxData, txData); - transferBit(5, &rxData, txData); - transferBit(4, &rxData, txData); - transferBit(3, &rxData, txData); - transferBit(2, &rxData, txData); - transferBit(1, &rxData, txData); - transferBit(0, &rxData, txData); - return rxData; - } - -private: - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - bool MODE_CPHA(uint8_t mode) - { - return (mode & 1) != 0; - } - inline __attribute__((always_inline)) - bool MODE_CPOL(uint8_t mode) - { - return (mode & 2) != 0; - } - inline __attribute__((always_inline)) - void receiveBit(uint8_t bit, uint8_t* data) - { - if (MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); - } - nop; - nop; - fastDigitalWrite(SckPin, - MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); - if (fastDigitalRead(MisoPin)) { - *data |= 1 << bit; - } - if (!MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, MODE_CPOL(Mode)); - } - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void sendBit(uint8_t bit, uint8_t data) - { - if (MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); - } - fastDigitalWrite(MosiPin, data & (1 << bit)); - fastDigitalWrite(SckPin, - MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); - nop; - nop; - if (!MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, MODE_CPOL(Mode)); - } - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) - { - if (MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); - } - fastDigitalWrite(MosiPin, txData & (1 << bit)); - fastDigitalWrite(SckPin, - MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); - if (fastDigitalRead(MisoPin)) { - *rxData |= 1 << bit; - } - if (!MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, MODE_CPOL(Mode)); - } - } - //---------------------------------------------------------------------------- -}; -#endif // SoftSPI_h -/** @} */ diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/AvrDevelopersGpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/AvrDevelopersGpioPinMap.h deleted file mode 100644 index 3da10631..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/AvrDevelopersGpioPinMap.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef AvrDevelopersGpioPinMap_h -#define AvrDevelopersGpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(B, 0), // D0 - GPIO_PIN(B, 1), // D1 - GPIO_PIN(B, 2), // D2 - GPIO_PIN(B, 3), // D3 - GPIO_PIN(B, 4), // D4 - GPIO_PIN(B, 5), // D5 - GPIO_PIN(B, 6), // D6 - GPIO_PIN(B, 7), // D7 - GPIO_PIN(D, 0), // D8 - GPIO_PIN(D, 1), // D9 - GPIO_PIN(D, 2), // D10 - GPIO_PIN(D, 3), // D11 - GPIO_PIN(D, 4), // D12 - GPIO_PIN(D, 5), // D13 - GPIO_PIN(D, 6), // D14 - GPIO_PIN(D, 7), // D15 - GPIO_PIN(C, 0), // D16 - GPIO_PIN(C, 1), // D17 - GPIO_PIN(C, 2), // D18 - GPIO_PIN(C, 3), // D19 - GPIO_PIN(C, 4), // D20 - GPIO_PIN(C, 5), // D21 - GPIO_PIN(C, 6), // D22 - GPIO_PIN(C, 7), // D23 - GPIO_PIN(A, 7), // D24 - GPIO_PIN(A, 6), // D25 - GPIO_PIN(A, 5), // D26 - GPIO_PIN(A, 4), // D27 - GPIO_PIN(A, 3), // D28 - GPIO_PIN(A, 2), // D29 - GPIO_PIN(A, 1), // D30 - GPIO_PIN(A, 0) // D31 -}; -#endif // AvrDevelopersGpioPinMap_h \ No newline at end of file diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/BobuinoGpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/BobuinoGpioPinMap.h deleted file mode 100644 index 170611a5..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/BobuinoGpioPinMap.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef BobuinoGpioPinMap_h -#define BobuinoGpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(B, 0), // D0 - GPIO_PIN(B, 1), // D1 - GPIO_PIN(B, 2), // D2 - GPIO_PIN(B, 3), // D3 - GPIO_PIN(B, 4), // D4 - GPIO_PIN(B, 5), // D5 - GPIO_PIN(B, 6), // D6 - GPIO_PIN(B, 7), // D7 - GPIO_PIN(D, 0), // D8 - GPIO_PIN(D, 1), // D9 - GPIO_PIN(D, 2), // D10 - GPIO_PIN(D, 3), // D11 - GPIO_PIN(D, 4), // D12 - GPIO_PIN(D, 5), // D13 - GPIO_PIN(D, 6), // D14 - GPIO_PIN(D, 7), // D15 - GPIO_PIN(C, 0), // D16 - GPIO_PIN(C, 1), // D17 - GPIO_PIN(C, 2), // D18 - GPIO_PIN(C, 3), // D19 - GPIO_PIN(C, 4), // D20 - GPIO_PIN(C, 5), // D21 - GPIO_PIN(C, 6), // D22 - GPIO_PIN(C, 7), // D23 - GPIO_PIN(A, 0), // D24 - GPIO_PIN(A, 1), // D25 - GPIO_PIN(A, 2), // D26 - GPIO_PIN(A, 3), // D27 - GPIO_PIN(A, 4), // D28 - GPIO_PIN(A, 5), // D29 - GPIO_PIN(A, 6), // D30 - GPIO_PIN(A, 7) // D31 -}; -#endif // BobuinoGpioPinMap_h \ No newline at end of file diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/GpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/GpioPinMap.h deleted file mode 100644 index 901ad3e7..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/GpioPinMap.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library 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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -#ifndef GpioPinMap_h -#define GpioPinMap_h -#if defined(__AVR_ATmega168__)\ -||defined(__AVR_ATmega168P__)\ -||defined(__AVR_ATmega328P__) -// 168 and 328 Arduinos -#include "UnoGpioPinMap.h" -#elif defined(__AVR_ATmega1280__)\ -|| defined(__AVR_ATmega2560__) -// Mega ADK -#include "MegaGpioPinMap.h" -#elif defined(__AVR_ATmega32U4__) -#ifdef CORE_TEENSY -#include "Teensy2GpioPinMap.h" -#else // CORE_TEENSY -// Leonardo or Yun -#include "LeonardoGpioPinMap.h" -#endif // CORE_TEENSY -#elif defined(__AVR_AT90USB646__)\ -|| defined(__AVR_AT90USB1286__) -// Teensy++ 1.0 & 2.0 -#include "Teensy2ppGpioPinMap.h" -#elif defined(__AVR_ATmega1284P__)\ -|| defined(__AVR_ATmega1284__)\ -|| defined(__AVR_ATmega644P__)\ -|| defined(__AVR_ATmega644__)\ -|| defined(__AVR_ATmega64__)\ -|| defined(__AVR_ATmega32__)\ -|| defined(__AVR_ATmega324__)\ -|| defined(__AVR_ATmega16__) -#ifdef ARDUINO_1284P_AVR_DEVELOPERS -#include "AvrDevelopersGpioPinMap.h" -#elif defined(ARDUINO_1284P_BOBUINO) -#include "BobuinoGpioPinMap.h" -#elif defined(ARDUINO_1284P_SLEEPINGBEAUTY) -#include "SleepingBeautyGpioPinMap.h" -#elif defined(ARDUINO_1284P_STANDARD) -#include "Standard1284GpioPinMap.h" -#else // ARDUINO_1284P_SLEEPINGBEAUTY -#error Undefined variant 1284, 644, 324 -#endif // ARDUINO_1284P_SLEEPINGBEAUTY -#else // 1284P, 1284, 644 -#error Unknown board type. -#endif // end all boards -#endif // GpioPinMap_h diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/LeonardoGpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/LeonardoGpioPinMap.h deleted file mode 100644 index 48e17345..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/LeonardoGpioPinMap.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef LeonardoGpioPinMap_h -#define LeonardoGpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(D, 2), // D0 - GPIO_PIN(D, 3), // D1 - GPIO_PIN(D, 1), // D2 - GPIO_PIN(D, 0), // D3 - GPIO_PIN(D, 4), // D4 - GPIO_PIN(C, 6), // D5 - GPIO_PIN(D, 7), // D6 - GPIO_PIN(E, 6), // D7 - GPIO_PIN(B, 4), // D8 - GPIO_PIN(B, 5), // D9 - GPIO_PIN(B, 6), // D10 - GPIO_PIN(B, 7), // D11 - GPIO_PIN(D, 6), // D12 - GPIO_PIN(C, 7), // D13 - GPIO_PIN(B, 3), // D14 - GPIO_PIN(B, 1), // D15 - GPIO_PIN(B, 2), // D16 - GPIO_PIN(B, 0), // D17 - GPIO_PIN(F, 7), // D18 - GPIO_PIN(F, 6), // D19 - GPIO_PIN(F, 5), // D20 - GPIO_PIN(F, 4), // D21 - GPIO_PIN(F, 1), // D22 - GPIO_PIN(F, 0), // D23 - GPIO_PIN(D, 4), // D24 - GPIO_PIN(D, 7), // D25 - GPIO_PIN(B, 4), // D26 - GPIO_PIN(B, 5), // D27 - GPIO_PIN(B, 6), // D28 - GPIO_PIN(D, 6) // D29 -}; -#endif // LeonardoGpioPinMap_h diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/MegaGpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/MegaGpioPinMap.h deleted file mode 100644 index aded09a6..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/MegaGpioPinMap.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef MegaGpioPinMap_h -#define MegaGpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(E, 0), // D0 - GPIO_PIN(E, 1), // D1 - GPIO_PIN(E, 4), // D2 - GPIO_PIN(E, 5), // D3 - GPIO_PIN(G, 5), // D4 - GPIO_PIN(E, 3), // D5 - GPIO_PIN(H, 3), // D6 - GPIO_PIN(H, 4), // D7 - GPIO_PIN(H, 5), // D8 - GPIO_PIN(H, 6), // D9 - GPIO_PIN(B, 4), // D10 - GPIO_PIN(B, 5), // D11 - GPIO_PIN(B, 6), // D12 - GPIO_PIN(B, 7), // D13 - GPIO_PIN(J, 1), // D14 - GPIO_PIN(J, 0), // D15 - GPIO_PIN(H, 1), // D16 - GPIO_PIN(H, 0), // D17 - GPIO_PIN(D, 3), // D18 - GPIO_PIN(D, 2), // D19 - GPIO_PIN(D, 1), // D20 - GPIO_PIN(D, 0), // D21 - GPIO_PIN(A, 0), // D22 - GPIO_PIN(A, 1), // D23 - GPIO_PIN(A, 2), // D24 - GPIO_PIN(A, 3), // D25 - GPIO_PIN(A, 4), // D26 - GPIO_PIN(A, 5), // D27 - GPIO_PIN(A, 6), // D28 - GPIO_PIN(A, 7), // D29 - GPIO_PIN(C, 7), // D30 - GPIO_PIN(C, 6), // D31 - GPIO_PIN(C, 5), // D32 - GPIO_PIN(C, 4), // D33 - GPIO_PIN(C, 3), // D34 - GPIO_PIN(C, 2), // D35 - GPIO_PIN(C, 1), // D36 - GPIO_PIN(C, 0), // D37 - GPIO_PIN(D, 7), // D38 - GPIO_PIN(G, 2), // D39 - GPIO_PIN(G, 1), // D40 - GPIO_PIN(G, 0), // D41 - GPIO_PIN(L, 7), // D42 - GPIO_PIN(L, 6), // D43 - GPIO_PIN(L, 5), // D44 - GPIO_PIN(L, 4), // D45 - GPIO_PIN(L, 3), // D46 - GPIO_PIN(L, 2), // D47 - GPIO_PIN(L, 1), // D48 - GPIO_PIN(L, 0), // D49 - GPIO_PIN(B, 3), // D50 - GPIO_PIN(B, 2), // D51 - GPIO_PIN(B, 1), // D52 - GPIO_PIN(B, 0), // D53 - GPIO_PIN(F, 0), // D54 - GPIO_PIN(F, 1), // D55 - GPIO_PIN(F, 2), // D56 - GPIO_PIN(F, 3), // D57 - GPIO_PIN(F, 4), // D58 - GPIO_PIN(F, 5), // D59 - GPIO_PIN(F, 6), // D60 - GPIO_PIN(F, 7), // D61 - GPIO_PIN(K, 0), // D62 - GPIO_PIN(K, 1), // D63 - GPIO_PIN(K, 2), // D64 - GPIO_PIN(K, 3), // D65 - GPIO_PIN(K, 4), // D66 - GPIO_PIN(K, 5), // D67 - GPIO_PIN(K, 6), // D68 - GPIO_PIN(K, 7) // D69 -}; -#endif // MegaGpioPinMap_h diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/SleepingBeautyGpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/SleepingBeautyGpioPinMap.h deleted file mode 100644 index 3dacb1f4..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/SleepingBeautyGpioPinMap.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SleepingBeautyGpioPinMap_h -#define SleepingBeautyGpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(D, 0), // D0 - GPIO_PIN(D, 1), // D1 - GPIO_PIN(D, 2), // D2 - GPIO_PIN(D, 3), // D3 - GPIO_PIN(B, 0), // D4 - GPIO_PIN(B, 1), // D5 - GPIO_PIN(B, 2), // D6 - GPIO_PIN(B, 3), // D7 - GPIO_PIN(D, 6), // D8 - GPIO_PIN(D, 5), // D9 - GPIO_PIN(B, 4), // D10 - GPIO_PIN(B, 5), // D11 - GPIO_PIN(B, 6), // D12 - GPIO_PIN(B, 7), // D13 - GPIO_PIN(C, 7), // D14 - GPIO_PIN(C, 6), // D15 - GPIO_PIN(A, 5), // D16 - GPIO_PIN(A, 4), // D17 - GPIO_PIN(A, 3), // D18 - GPIO_PIN(A, 2), // D19 - GPIO_PIN(A, 1), // D20 - GPIO_PIN(A, 0), // D21 - GPIO_PIN(D, 4), // D22 - GPIO_PIN(D, 7), // D23 - GPIO_PIN(C, 2), // D24 - GPIO_PIN(C, 3), // D25 - GPIO_PIN(C, 4), // D26 - GPIO_PIN(C, 5), // D27 - GPIO_PIN(C, 1), // D28 - GPIO_PIN(C, 0), // D29 - GPIO_PIN(A, 6), // D30 - GPIO_PIN(A, 7) // D31 -}; -#endif // SleepingBeautyGpioPinMap_h \ No newline at end of file diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Standard1284GpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Standard1284GpioPinMap.h deleted file mode 100644 index 887797a6..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Standard1284GpioPinMap.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef Standard1284GpioPinMap_h -#define Standard1284GpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(B, 0), // D0 - GPIO_PIN(B, 1), // D1 - GPIO_PIN(B, 2), // D2 - GPIO_PIN(B, 3), // D3 - GPIO_PIN(B, 4), // D4 - GPIO_PIN(B, 5), // D5 - GPIO_PIN(B, 6), // D6 - GPIO_PIN(B, 7), // D7 - GPIO_PIN(D, 0), // D8 - GPIO_PIN(D, 1), // D9 - GPIO_PIN(D, 2), // D10 - GPIO_PIN(D, 3), // D11 - GPIO_PIN(D, 4), // D12 - GPIO_PIN(D, 5), // D13 - GPIO_PIN(D, 6), // D14 - GPIO_PIN(D, 7), // D15 - GPIO_PIN(C, 0), // D16 - GPIO_PIN(C, 1), // D17 - GPIO_PIN(C, 2), // D18 - GPIO_PIN(C, 3), // D19 - GPIO_PIN(C, 4), // D20 - GPIO_PIN(C, 5), // D21 - GPIO_PIN(C, 6), // D22 - GPIO_PIN(C, 7), // D23 - GPIO_PIN(A, 0), // D24 - GPIO_PIN(A, 1), // D25 - GPIO_PIN(A, 2), // D26 - GPIO_PIN(A, 3), // D27 - GPIO_PIN(A, 4), // D28 - GPIO_PIN(A, 5), // D29 - GPIO_PIN(A, 6), // D30 - GPIO_PIN(A, 7) // D31 -}; -#endif // Standard1284GpioPinMap_h \ No newline at end of file diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Teensy2GpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Teensy2GpioPinMap.h deleted file mode 100644 index 90515965..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Teensy2GpioPinMap.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef Teensy2GpioPinMap_h -#define Teensy2GpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(B, 0), // D0 - GPIO_PIN(B, 1), // D1 - GPIO_PIN(B, 2), // D2 - GPIO_PIN(B, 3), // D3 - GPIO_PIN(B, 7), // D4 - GPIO_PIN(D, 0), // D5 - GPIO_PIN(D, 1), // D6 - GPIO_PIN(D, 2), // D7 - GPIO_PIN(D, 3), // D8 - GPIO_PIN(C, 6), // D9 - GPIO_PIN(C, 7), // D10 - GPIO_PIN(D, 6), // D11 - GPIO_PIN(D, 7), // D12 - GPIO_PIN(B, 4), // D13 - GPIO_PIN(B, 5), // D14 - GPIO_PIN(B, 6), // D15 - GPIO_PIN(F, 7), // D16 - GPIO_PIN(F, 6), // D17 - GPIO_PIN(F, 5), // D18 - GPIO_PIN(F, 4), // D19 - GPIO_PIN(F, 1), // D20 - GPIO_PIN(F, 0), // D21 - GPIO_PIN(D, 4), // D22 - GPIO_PIN(D, 5), // D23 - GPIO_PIN(E, 6), // D24 -}; -#endif // Teensy2GpioPinMap_h diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Teensy2ppGpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Teensy2ppGpioPinMap.h deleted file mode 100644 index e184f6c1..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/Teensy2ppGpioPinMap.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef Teensypp2GpioPinMap_h -#define Teensypp2GpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(D, 0), // D0 - GPIO_PIN(D, 1), // D1 - GPIO_PIN(D, 2), // D2 - GPIO_PIN(D, 3), // D3 - GPIO_PIN(D, 4), // D4 - GPIO_PIN(D, 5), // D5 - GPIO_PIN(D, 6), // D6 - GPIO_PIN(D, 7), // D7 - GPIO_PIN(E, 0), // D8 - GPIO_PIN(E, 1), // D9 - GPIO_PIN(C, 0), // D10 - GPIO_PIN(C, 1), // D11 - GPIO_PIN(C, 2), // D12 - GPIO_PIN(C, 3), // D13 - GPIO_PIN(C, 4), // D14 - GPIO_PIN(C, 5), // D15 - GPIO_PIN(C, 6), // D16 - GPIO_PIN(C, 7), // D17 - GPIO_PIN(E, 6), // D18 - GPIO_PIN(E, 7), // D19 - GPIO_PIN(B, 0), // D20 - GPIO_PIN(B, 1), // D21 - GPIO_PIN(B, 2), // D22 - GPIO_PIN(B, 3), // D23 - GPIO_PIN(B, 4), // D24 - GPIO_PIN(B, 5), // D25 - GPIO_PIN(B, 6), // D26 - GPIO_PIN(B, 7), // D27 - GPIO_PIN(A, 0), // D28 - GPIO_PIN(A, 1), // D29 - GPIO_PIN(A, 2), // D30 - GPIO_PIN(A, 3), // D31 - GPIO_PIN(A, 4), // D32 - GPIO_PIN(A, 5), // D33 - GPIO_PIN(A, 6), // D34 - GPIO_PIN(A, 7), // D35 - GPIO_PIN(E, 4), // D36 - GPIO_PIN(E, 5), // D37 - GPIO_PIN(F, 0), // D38 - GPIO_PIN(F, 1), // D39 - GPIO_PIN(F, 2), // D40 - GPIO_PIN(F, 3), // D41 - GPIO_PIN(F, 4), // D42 - GPIO_PIN(F, 5), // D43 - GPIO_PIN(F, 6), // D44 - GPIO_PIN(F, 7), // D45 -}; -#endif // Teensypp2GpioPinMap_h diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/UnoGpioPinMap.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/UnoGpioPinMap.h deleted file mode 100644 index 4b82e82b..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalIO/boards/UnoGpioPinMap.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef UnoGpioPinMap_h -#define UnoGpioPinMap_h -static const GpioPinMap_t GpioPinMap[] = { - GPIO_PIN(D, 0), // D0 - GPIO_PIN(D, 1), // D1 - GPIO_PIN(D, 2), // D2 - GPIO_PIN(D, 3), // D3 - GPIO_PIN(D, 4), // D4 - GPIO_PIN(D, 5), // D5 - GPIO_PIN(D, 6), // D6 - GPIO_PIN(D, 7), // D7 - GPIO_PIN(B, 0), // D8 - GPIO_PIN(B, 1), // D9 - GPIO_PIN(B, 2), // D10 - GPIO_PIN(B, 3), // D11 - GPIO_PIN(B, 4), // D12 - GPIO_PIN(B, 5), // D13 - GPIO_PIN(C, 0), // D14 - GPIO_PIN(C, 1), // D15 - GPIO_PIN(C, 2), // D16 - GPIO_PIN(C, 3), // D17 - GPIO_PIN(C, 4), // D18 - GPIO_PIN(C, 5) // D19 -}; -#endif // UnoGpioPinMap_h \ No newline at end of file diff --git a/lib/MySensors/hal/architecture/AVR/drivers/DigitalWriteFast/digitalWriteFast.h b/lib/MySensors/hal/architecture/AVR/drivers/DigitalWriteFast/digitalWriteFast.h deleted file mode 100644 index 1cf5bde8..00000000 --- a/lib/MySensors/hal/architecture/AVR/drivers/DigitalWriteFast/digitalWriteFast.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Optimized digital functions for AVR microcontrollers - * based on http://code.google.com/p/digitalwritefast - */ - -#ifndef __digitalWriteFast_h_ -#define __digitalWriteFast_h_ - -#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_DUEMILANOVE) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || defined (__AVR_ATmega168__) -#if defined(__AVR_ATmega328PB__) -#define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTD : (((__pin) >= 8 && (__pin) <= 13) ? &PORTB : (((__pin) >= 14 && (__pin) <= 19) ? &PORTC : &PORTE))) -#define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRD : (((__pin) >= 8 && (__pin) <= 13) ? &DDRB : (((__pin) >= 14 && (__pin) <= 19) ? &DDRC : &DDRE))) -#define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PIND : (((__pin) >= 8 && (__pin) <= 13) ? &PINB : (((__pin) >= 14 && (__pin) <= 19) ? &PINC : &PINE))) -#define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 13) ? (__pin) - 8 : (((__pin) >= 14 && (__pin) <= 19) ? (__pin) - 14 : (((__pin) >= 20 && (__pin) <= 21) ? (__pin) - 18 : (__pin) - 22)))) -#else -#define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTD : (((__pin) >= 8 && (__pin) <= 13) ? &PORTB : &PORTC)) -#define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRD : (((__pin) >= 8 && (__pin) <= 13) ? &DDRB : &DDRC)) -#define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PIND : (((__pin) >= 8 && (__pin) <= 13) ? &PINB : &PINC)) -#define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 13) ? (__pin) - 8 : (__pin) - 14)) -#endif -#define digitalWriteFast(__pin, __value) do { if (__builtin_constant_p(__pin) && __builtin_constant_p(__value)) { bitWrite(*__digitalPinToPortReg(__pin), (uint8_t)__digitalPinToBit(__pin), (__value)); } else { digitalWrite((__pin), (__value)); } } while (0) -#define pinModeFast(__pin, __mode) do { if (__builtin_constant_p(__pin) && __builtin_constant_p(__mode) && (__mode!=INPUT_PULLUP)) { bitWrite(*__digitalPinToDDRReg(__pin), (uint8_t)__digitalPinToBit(__pin), (__mode)); } else { pinMode((__pin), (__mode)); } } while (0) -#define digitalReadFast(__pin) ( (bool) (__builtin_constant_p(__pin) ) ? (( bitRead(*__digitalPinToPINReg(__pin), (uint8_t)__digitalPinToBit(__pin))) ) : digitalRead((__pin)) ) -#else -// for all other archs use built-in pin access functions -#define digitalWriteFast(__pin, __value) digitalWrite(__pin, __value) -#define pinModeFast(__pin, __value) pinMode(__pin, __value) -#define digitalReadFast(__pin) digitalRead(__pin) -#endif - -#endif \ No newline at end of file diff --git a/lib/MySensors/hal/architecture/ESP32/MyHwESP32.cpp b/lib/MySensors/hal/architecture/ESP32/MyHwESP32.cpp deleted file mode 100644 index a7a0a599..00000000 --- a/lib/MySensors/hal/architecture/ESP32/MyHwESP32.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Arduino core for ESP32: https://github.com/espressif/arduino-esp32 - * - * MySensors ESP32 implementation, Copyright (C) 2017-2018 Olivier Mauti - * - */ - -#include "MyHwESP32.h" - -bool hwInit(void) -{ -#if !defined(MY_DISABLED_SERIAL) - MY_SERIALDEVICE.begin(MY_BAUD_RATE, SERIAL_8N1); -#if defined(MY_GATEWAY_SERIAL) - while (!MY_SERIALDEVICE) {} -#endif -#endif - return EEPROM.begin(MY_EEPROM_SIZE); -} - -void hwReadConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *dst = static_cast(buf); - int offs = reinterpret_cast(addr); - while (length-- > 0) { - *dst++ = EEPROM.read(offs++); - } -} - -void hwWriteConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *src = static_cast(buf); - int offs = reinterpret_cast(addr); - while (length-- > 0) { - EEPROM.write(offs++, *src++); - } - EEPROM.commit(); -} - -uint8_t hwReadConfig(const int addr) -{ - uint8_t value; - hwReadConfigBlock(&value, reinterpret_cast(addr), 1); - return value; -} - -void hwWriteConfig(const int addr, uint8_t value) -{ - if (hwReadConfig(addr) != value) { - hwWriteConfigBlock(&value, reinterpret_cast(addr), 1); - } -} - -bool hwUniqueID(unique_id_t *uniqueID) -{ - uint64_t val = ESP.getEfuseMac(); - (void)memcpy((void *)uniqueID, (void *)&val, 8); - (void)memset((void *)(uniqueID + 8), MY_HWID_PADDING_BYTE, 8); // padding - return true; -} - -ssize_t hwGetentropy(void *__buffer, size_t __length) -{ - // cut length if > 256 - if (__length > 256) { - __length = 256; - } - uint8_t *dst = (uint8_t *)__buffer; - // get random numbers - for (size_t i = 0; i < __length; i++) { - dst[i] = (uint8_t)esp_random(); - } - return __length; -} - -int8_t hwSleep(uint32_t ms) -{ - // TODO: Not supported! - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt; - (void)mode; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, - uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -uint16_t hwCPUVoltage(void) -{ - // in mV - return FUNCTION_NOT_SUPPORTED; -} - -uint16_t hwCPUFrequency(void) -{ - // in 1/10Mhz - return static_cast(ESP.getCpuFreqMHz() * 10); -} - -int8_t hwCPUTemperature(void) -{ - // CPU temperature in °C - return static_cast((temperatureRead() - MY_ESP32_TEMPERATURE_OFFSET) / - MY_ESP32_TEMPERATURE_GAIN); -} - -uint16_t hwFreeMem(void) -{ - return static_cast(ESP.getFreeHeap()); -} diff --git a/lib/MySensors/hal/architecture/ESP32/MyHwESP32.h b/lib/MySensors/hal/architecture/ESP32/MyHwESP32.h deleted file mode 100644 index 49b855a3..00000000 --- a/lib/MySensors/hal/architecture/ESP32/MyHwESP32.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Arduino core for ESP32: https://github.com/espressif/arduino-esp32 - * - * MySensors ESP32 implementation, Copyright (C) 2017-2018 Olivier Mauti - * - * Radio wiring ESP32(Node32s): RF24, RFM69, RFM95: - * - * | IO | RF24 | RFM69 | RFM95 | - * |------|------|-------|-------| - * | MOSI | 23 | 23 | 23 | - * | MISO | 19 | 19 | 19 | - * | SCK | 18 | 18 | 18 | - * | CSN | 5 | 5 | 5 | - * | CE | 17 | - | - | - * | RST | - | 17 | 17 | - * | IRQ | 16* | 16 | 16 | - * * = optional - * - */ - -#ifndef MyHwESP32_h -#define MyHwESP32_h - -#include -#include "EEPROM.h" -#include - -#ifdef __cplusplus -#include -#endif - -#define CRYPTO_LITTLE_ENDIAN - -#ifndef MY_SERIALDEVICE -#define MY_SERIALDEVICE Serial -#endif - -#ifndef MY_DEBUGDEVICE -#define MY_DEBUGDEVICE MY_SERIALDEVICE -#endif - -#ifndef MY_ESP32_TEMPERATURE_OFFSET -#define MY_ESP32_TEMPERATURE_OFFSET (0.0f) -#endif - -#ifndef MY_ESP32_TEMPERATURE_GAIN -#define MY_ESP32_TEMPERATURE_GAIN (1.0f) -#endif - -#define MY_EEPROM_SIZE 1024 - -#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value) -#define hwDigitalRead(__pin) digitalRead(__pin) -#define hwPinMode(__pin, __value) pinMode(__pin, __value) -#define hwWatchdogReset() -#define hwReboot() ESP.restart() -#define hwMillis() millis() -#define hwMicros() micros() -#define hwRandomNumberInit() randomSeed(esp_random()) -#define hwGetSleepRemaining() (0ul) - -bool hwInit(void); -void hwReadConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfig(const int addr, uint8_t value); -uint8_t hwReadConfig(const int addr); -ssize_t hwGetentropy(void *__buffer, size_t __length); -#define MY_HW_HAS_GETENTROPY - -// SOFTSPI -#ifdef MY_SOFTSPI -#error Soft SPI is not available on this architecture! -#endif -#define hwSPI SPI //!< hwSPI - -/** -* Restore interrupt state. -* Helper function for MY_CRITICAL_SECTION. -*/ -static __inline__ void __psRestore(const uint32_t *__s) -{ - XTOS_RESTORE_INTLEVEL(*__s); -} - -#ifndef DOXYGEN -#define MY_CRITICAL_SECTION for ( uint32_t __psSaved __attribute__((__cleanup__(__psRestore))) = XTOS_DISABLE_ALL_INTERRUPTS, __ToDo = 1; __ToDo ; __ToDo = 0 ) -#endif /* DOXYGEN */ - - -#endif diff --git a/lib/MySensors/hal/architecture/ESP32/MyMainESP32.cpp b/lib/MySensors/hal/architecture/ESP32/MyMainESP32.cpp deleted file mode 100644 index 6939f2f8..00000000 --- a/lib/MySensors/hal/architecture/ESP32/MyMainESP32.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -*/ - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_task_wdt.h" -#include "Arduino.h" - -TaskHandle_t loopTaskHandle = NULL; - -#if CONFIG_AUTOSTART_ARDUINO - -#if CONFIG_FREERTOS_UNICORE -#define ARDUINO_RUNNING_CORE 0 -#else -#define ARDUINO_RUNNING_CORE 1 -#endif - -bool loopTaskWDTEnabled; - -void loopTask(void *pvParameters) -{ - _begin(); // Startup MySensors library - for(;;) { - if(loopTaskWDTEnabled) { - esp_task_wdt_reset(); - } - _process(); // Process incoming data - loop(); - } -} - -extern "C" void app_main() -{ - loopTaskWDTEnabled = false; - initArduino(); - xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE); -} - -#endif diff --git a/lib/MySensors/hal/architecture/ESP8266/MyHwESP8266.cpp b/lib/MySensors/hal/architecture/ESP8266/MyHwESP8266.cpp deleted file mode 100644 index 75a149b5..00000000 --- a/lib/MySensors/hal/architecture/ESP8266/MyHwESP8266.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHwESP8266.h" - -bool hwInit(void) -{ -#if !defined(MY_DISABLED_SERIAL) - MY_SERIALDEVICE.begin(MY_BAUD_RATE, SERIAL_8N1, MY_ESP8266_SERIAL_MODE, 1); - MY_SERIALDEVICE.setDebugOutput(true); -#if defined(MY_GATEWAY_SERIAL) - while (!MY_SERIALDEVICE) {} -#endif -#endif - EEPROM.begin(EEPROM_size); - return true; -} - -void hwReadConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *dst = static_cast(buf); - int pos = reinterpret_cast(addr); - while (length-- > 0) { - *dst++ = EEPROM.read(pos++); - } -} - -void hwWriteConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *src = static_cast(buf); - int pos = reinterpret_cast(addr); - while (length-- > 0) { - EEPROM.write(pos++, *src++); - } - // see implementation, commit only executed if diff - EEPROM.commit(); -} - -uint8_t hwReadConfig(const int addr) -{ - uint8_t value; - hwReadConfigBlock(&value, reinterpret_cast(addr), 1); - return value; -} - -void hwWriteConfig(const int addr, uint8_t value) -{ - hwWriteConfigBlock(&value, reinterpret_cast(addr), 1); -} - -bool hwUniqueID(unique_id_t *uniqueID) -{ - // padding - (void)memset((uint8_t *)uniqueID, MY_HWID_PADDING_BYTE, sizeof(unique_id_t)); - uint32_t val = ESP.getChipId(); - (void)memcpy((uint8_t *)uniqueID, &val, 4); - val = ESP.getFlashChipId(); - (void)memcpy((uint8_t *)uniqueID + 4, &val, 4); - return true; -} - -ssize_t hwGetentropy(void *__buffer, size_t __length) -{ - // cut length if > 256 - if (__length > 256) { - __length = 256; - } - uint8_t *dst = (uint8_t *)__buffer; - - // Start random number generator - for (size_t i = 0; i < __length; i++) { - dst[i] = (uint8_t)RANDOM_REG32; - } - - return __length; -} - -int8_t hwSleep(uint32_t ms) -{ - // TODO: Not supported! - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt; - (void)mode; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, - uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -#if defined(MY_SPECIAL_DEBUG) -// settings for getVcc() -ADC_MODE(ADC_VCC); -#else -// [default] settings for analogRead(A0) -ADC_MODE(ADC_TOUT); -#endif - -uint16_t hwCPUVoltage(void) -{ -#if defined(MY_SPECIAL_DEBUG) - // in mV, requires ADC_VCC set - return ESP.getVcc(); -#else - // not possible - return FUNCTION_NOT_SUPPORTED; -#endif -} - -uint16_t hwCPUFrequency(void) -{ - // in 1/10Mhz - return ESP.getCpuFreqMHz()*10; -} - -int8_t hwCPUTemperature(void) -{ - return -127; // not available -} - -uint16_t hwFreeMem(void) -{ - return ESP.getFreeHeap(); -} diff --git a/lib/MySensors/hal/architecture/ESP8266/MyHwESP8266.h b/lib/MySensors/hal/architecture/ESP8266/MyHwESP8266.h deleted file mode 100644 index 5b6f157f..00000000 --- a/lib/MySensors/hal/architecture/ESP8266/MyHwESP8266.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ -#ifndef MyHwESP8266_h -#define MyHwESP8266_h - -#include -#include -#include -#include - -#ifdef __cplusplus -#include -#endif - -#define CRYPTO_LITTLE_ENDIAN - -#ifndef MY_SERIALDEVICE -#define MY_SERIALDEVICE Serial -#endif - -#ifndef MY_DEBUGDEVICE -#define MY_DEBUGDEVICE MY_SERIALDEVICE -#endif - -#define EEPROM_size (1024) - -// Define these as macros to save valuable space -#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value) -#define hwDigitalRead(__pin) digitalRead(__pin) -#define hwPinMode(__pin, __value) pinMode(__pin, __value) -#define hwWatchdogReset() wdt_reset() -#define hwReboot() ESP.restart() -#define hwMillis() millis() -// The use of randomSeed switch to pseudo random number. Keep hwRandomNumberInit empty -#define hwRandomNumberInit() -#define hwGetSleepRemaining() (0ul) - -bool hwInit(void); -void hwReadConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfig(const int addr, uint8_t value); -uint8_t hwReadConfig(const int addr); -ssize_t hwGetentropy(void *__buffer, size_t __length); -//#define MY_HW_HAS_GETENTROPY - -// SOFTSPI -#ifdef MY_SOFTSPI -#error Soft SPI is not available on this architecture! -#endif -#define hwSPI SPI //!< hwSPI - - -/** - * Restore interrupt state. - * Helper function for MY_CRITICAL_SECTION. - */ -static __inline__ void __psRestore(const uint32_t *__s) -{ - xt_wsr_ps( *__s ); -} - -#ifndef DOXYGEN -#define MY_CRITICAL_SECTION for ( uint32_t __psSaved __attribute__((__cleanup__(__psRestore))) = xt_rsil(15), __ToDo = 1; __ToDo ; __ToDo = 0 ) -#endif /* DOXYGEN */ - -#endif // #ifdef ARDUINO_ARCH_ESP8266 diff --git a/lib/MySensors/hal/architecture/ESP8266/MyMainESP8266.cpp b/lib/MySensors/hal/architecture/ESP8266/MyMainESP8266.cpp deleted file mode 100644 index 4b7298a0..00000000 --- a/lib/MySensors/hal/architecture/ESP8266/MyMainESP8266.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -//This may be used to change user task stack size: -//#define CONT_STACKSIZE 4096 -#include -#include "Schedule.h" -extern "C" { -#include "ets_sys.h" -#include "os_type.h" -#include "osapi.h" -#include "mem.h" -#include "user_interface.h" -#include "cont.h" -} -#include -#include "gdb_hooks.h" - -#define LOOP_TASK_PRIORITY 1 -#define LOOP_QUEUE_SIZE 1 -#define OPTIMISTIC_YIELD_TIME_US 16000 - -extern "C" void call_user_start(); -extern void loop(); -extern void setup(); -extern void(*__init_array_start)(void); -extern void(*__init_array_end)(void); - -/* Not static, used in Esp.cpp */ -struct rst_info resetInfo; - -/* Not static, used in core_esp8266_postmortem.c and other places. - * Placed into noinit section because we assign value to this variable - * before .bss is zero-filled, and need to preserve the value. - */ -cont_t* g_pcont __attribute__((section(".noinit"))); - -/* Event queue used by the main (arduino) task */ -static os_event_t s_loop_queue[LOOP_QUEUE_SIZE]; - -/* Used to implement optimistic_yield */ -static uint32_t s_micros_at_task_start; - -/* For ets_intr_lock_nest / ets_intr_unlock_nest - * Max nesting seen by SDK so far is 2. - */ -#define ETS_INTR_LOCK_NEST_MAX 7 -static uint16_t ets_intr_lock_stack[ETS_INTR_LOCK_NEST_MAX]; -static byte ets_intr_lock_stack_ptr = 0; - - -extern "C" { - extern const uint32_t __attribute__((section(".ver_number"))) core_version = - ARDUINO_ESP8266_GIT_VER; - const char* core_release = -#ifdef ARDUINO_ESP8266_RELEASE - ARDUINO_ESP8266_RELEASE; -#else - NULL; -#endif -} // extern "C" - -void initVariant() __attribute__((weak)); -void initVariant() -{ -} - -void preloop_update_frequency() __attribute__((weak)); -void preloop_update_frequency() -{ -#if defined(F_CPU) && (F_CPU == 160000000L) - REG_SET_BIT(0x3ff00014, BIT(0)); - ets_update_cpu_frequency(160); -#endif -} - -extern "C" bool can_yield() -{ - return cont_can_yield(g_pcont); -} - -static inline void esp_yield_within_cont() __attribute__((always_inline)); -static void esp_yield_within_cont() -{ - cont_yield(g_pcont); - run_scheduled_recurrent_functions(); -} - -extern "C" void esp_yield() -{ - if (can_yield()) { - esp_yield_within_cont(); - } -} - -extern "C" void esp_schedule() -{ - // always on CONT stack here - ets_post(LOOP_TASK_PRIORITY, 0, 0); -} - -extern "C" void __yield() -{ - if (can_yield()) { - esp_schedule(); - esp_yield_within_cont(); - } else { - panic(); - } -} - -extern "C" void yield(void) __attribute__((weak, alias("__yield"))); - -extern "C" void optimistic_yield(uint32_t interval_us) -{ - if (can_yield() && - (system_get_time() - s_micros_at_task_start) > interval_us) { - yield(); - } -} - - -// Replace ets_intr_(un)lock with nestable versions -extern "C" void IRAM_ATTR ets_intr_lock() -{ - if (ets_intr_lock_stack_ptr < ETS_INTR_LOCK_NEST_MAX) { - ets_intr_lock_stack[ets_intr_lock_stack_ptr++] = xt_rsil(3); - } else { - xt_rsil(3); - } -} - -extern "C" void IRAM_ATTR ets_intr_unlock() -{ - if (ets_intr_lock_stack_ptr > 0) { - xt_wsr_ps(ets_intr_lock_stack[--ets_intr_lock_stack_ptr]); - } else { - xt_rsil(0); - } -} - - -// Save / Restore the PS state across the rom ets_post call as the rom code -// does not implement this correctly. -extern "C" bool ets_post_rom(uint8 prio, ETSSignal sig, ETSParam par); - -extern "C" bool IRAM_ATTR ets_post(uint8 prio, ETSSignal sig, ETSParam par) -{ - uint32_t saved; - asm volatile ("rsr %0,ps":"=a" (saved)); - bool rc = ets_post_rom(prio, sig, par); - xt_wsr_ps(saved); - return rc; -} - -extern "C" void __loop_end(void) -{ - run_scheduled_functions(); - run_scheduled_recurrent_functions(); -} - -extern "C" void loop_end(void) __attribute__((weak, alias("__loop_end"))); - -static void loop_wrapper() -{ - static bool setup_done = false; - preloop_update_frequency(); - if (!setup_done) { - _begin(); // Startup MySensors library - setup_done = true; - } - _process(); // Process incoming data - loop(); - run_scheduled_functions(); - esp_schedule(); -} - -static void loop_task(os_event_t *events) -{ - (void)events; - s_micros_at_task_start = system_get_time(); - cont_run(g_pcont, &loop_wrapper); - if (cont_check(g_pcont) != 0) { - panic(); - } -} -extern "C" { - - struct object { - long placeholder[10]; - }; - void __register_frame_info(const void *begin, struct object *ob); - extern char __eh_frame[]; -} - -static void do_global_ctors(void) -{ - static struct object ob; - __register_frame_info(__eh_frame, &ob); - - void(**p)(void) = &__init_array_end; - while (p != &__init_array_start) { - (*--p)(); - } -} - -extern "C" { - extern void __unhandled_exception(const char *str); - - static void __unhandled_exception_cpp() - { -#ifndef __EXCEPTIONS - abort(); -#else - static bool terminating; - if (terminating) { - abort(); - } - terminating = true; - /* Use a trick from vterminate.cc to get any std::exception what() */ - try { - __throw_exception_again; - } catch (const std::exception& e) { - __unhandled_exception(e.what()); - } catch (...) { - __unhandled_exception(""); - } -#endif - } - -} - -void init_done() -{ - system_set_os_print(1); - gdb_init(); - std::set_terminate(__unhandled_exception_cpp); - do_global_ctors(); - esp_schedule(); -} - -/* This is the entry point of the application. - * It gets called on the default stack, which grows down from the top - * of DRAM area. - * .bss has not been zeroed out yet, but .data and .rodata are in place. - * Cache is not enabled, so only ROM and IRAM functions can be called. - * Peripherals (except for SPI0 and UART0) are not initialized. - * This function does not return. - */ -/* - A bit of explanation for this entry point: - - SYS is the SDK task/context used by the upperlying system to run its - administrative tasks (at least WLAN and lwip's receive callbacks and - Ticker). NONOS-SDK is designed to run user's non-threaded code in - another specific task/context with its own stack in BSS. - - Some clever fellows found that the SYS stack was a large and quite unused - piece of ram that we could use for the user's stack instead of using user's - main memory, thus saving around 4KB on ram/heap. - - A problem arose later, which is that this stack can heavily be used by - the SDK for some features. One of these features is WPS. We still don't - know if other features are using this, or if this memory is going to be - used in future SDK releases. - - WPS beeing flawed by its poor security, or not beeing used by lots of - users, it has been decided that we are still going to use that memory for - user's stack and disable the use of WPS. - - app_entry() jumps to app_entry_custom() defined as "weakref" calling - itself a weak customizable function, allowing to use another one when - this is required (see core_esp8266_app_entry_noextra4k.cpp, used by WPS). - - (note: setting app_entry() itself as "weak" is not sufficient and always - ends up with the other "noextra4k" one linked, maybe because it has a - default ENTRY(app_entry) value in linker scripts). - - References: - https://github.com/esp8266/Arduino/pull/4553 - https://github.com/esp8266/Arduino/pull/4622 - https://github.com/esp8266/Arduino/issues/4779 - https://github.com/esp8266/Arduino/pull/4889 - -*/ - -extern "C" void app_entry_redefinable(void) __attribute__((weak)); -extern "C" void app_entry_redefinable(void) -{ - /* Allocate continuation context on this SYS stack, - and save pointer to it. */ - cont_t s_cont __attribute__((aligned(16))); - g_pcont = &s_cont; - - /* Call the entry point of the SDK code. */ - call_user_start(); -} - -static void app_entry_custom(void) __attribute__((weakref("app_entry_redefinable"))); - -extern "C" void app_entry(void) -{ - return app_entry_custom(); -} - -extern "C" void preinit(void) __attribute__((weak)); -extern "C" void preinit(void) -{ - /* do nothing by default */ -} - -extern "C" void user_init(void) -{ - struct rst_info *rtc_info_ptr = system_get_rst_info(); - memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo)); - - uart_div_modify(0, UART_CLK_FREQ / (115200)); - - init(); // in core_esp8266_wiring.c, inits hw regs and sdk timer - - initVariant(); - - cont_init(g_pcont); - - preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable. - - ets_task(loop_task, - LOOP_TASK_PRIORITY, s_loop_queue, - LOOP_QUEUE_SIZE); - - system_init_done_cb(&init_done); -} diff --git a/lib/MySensors/hal/architecture/Linux/MyHwLinuxGeneric.cpp b/lib/MySensors/hal/architecture/Linux/MyHwLinuxGeneric.cpp deleted file mode 100644 index 351d248b..00000000 --- a/lib/MySensors/hal/architecture/Linux/MyHwLinuxGeneric.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHwLinuxGeneric.h" - -static SoftEeprom eeprom; -static FILE *randomFp = NULL; - -bool hwInit(void) -{ - MY_SERIALDEVICE.begin(MY_BAUD_RATE); -#ifdef MY_GATEWAY_SERIAL -#ifdef MY_LINUX_SERIAL_GROUPNAME - if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) { - logError("Unable to change permission for serial port device.\n"); - exit(1); - } -#endif -#endif - - if (eeprom.init(conf.eeprom_file, conf.eeprom_size) != 0) { - exit(1); - } - - return true; -} - -void hwReadConfigBlock(void *buf, void *addr, size_t length) -{ - eeprom.readBlock(buf, addr, length); -} - -void hwWriteConfigBlock(void *buf, void *addr, size_t length) -{ - eeprom.writeBlock(buf, addr, length); -} - -uint8_t hwReadConfig(const int addr) -{ - return eeprom.readByte(addr); -} - -void hwWriteConfig(const int addr, uint8_t value) -{ - eeprom.writeByte(addr, value); -} - -void hwRandomNumberInit(void) -{ - uint32_t seed=0; - - if (randomFp != NULL) { - fclose(randomFp); - } - if (!(randomFp = fopen("/dev/urandom", "r"))) { - logError("Cannot open '/dev/urandom'.\n"); - exit(2); - } - - while (hwGetentropy(&seed, sizeof(seed)) != sizeof(seed)); - randomSeed(seed); -} - -ssize_t hwGetentropy(void *__buffer, size_t __length) -{ - return(fread(__buffer, 1, __length, randomFp)); -} - -uint32_t hwMillis(void) -{ - return millis(); -} - -bool hwUniqueID(unique_id_t *uniqueID) -{ - // not implemented yet - (void)uniqueID; - return false; -} - -// Not supported! -int8_t hwSleep(uint32_t ms) -{ - (void)ms; - - return MY_SLEEP_NOT_POSSIBLE; -} - -// Not supported! -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms) -{ - (void)interrupt; - (void)mode; - (void)ms; - - return MY_SLEEP_NOT_POSSIBLE; -} - -// Not supported! -int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, - uint32_t ms) -{ - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - (void)ms; - - return MY_SLEEP_NOT_POSSIBLE; -} - -uint16_t hwCPUVoltage(void) -{ - // TODO: Not supported! - return FUNCTION_NOT_SUPPORTED; -} - -uint16_t hwCPUFrequency(void) -{ - // TODO: Not supported! - return FUNCTION_NOT_SUPPORTED; -} - -int8_t hwCPUTemperature(void) -{ - return -127; // not implemented yet -} - -uint16_t hwFreeMem(void) -{ - // TODO: Not supported! - return FUNCTION_NOT_SUPPORTED; -} - -void hwDigitalWrite(uint8_t pin, uint8_t value) -{ - digitalWrite(pin, value); -} - -int hwDigitalRead(uint8_t pin) -{ - return digitalRead(pin); -} - -void hwPinMode(uint8_t pin, uint8_t mode) -{ - pinMode(pin, mode); -} diff --git a/lib/MySensors/hal/architecture/Linux/MyHwLinuxGeneric.h b/lib/MySensors/hal/architecture/Linux/MyHwLinuxGeneric.h deleted file mode 100644 index 8d3f1e45..00000000 --- a/lib/MySensors/hal/architecture/Linux/MyHwLinuxGeneric.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyHwLinuxGeneric_h -#define MyHwLinuxGeneric_h - -#include -#include -#include "SerialPort.h" -#include "StdInOutStream.h" -#include -#include -#include -#include -#include -#include -#include -#include "SoftEeprom.h" -#include "log.h" -#include "config.h" - -#define CRYPTO_LITTLE_ENDIAN - -#ifdef MY_LINUX_SERIAL_PORT -#ifdef MY_LINUX_SERIAL_IS_PTY -SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT, true); -#else -SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT, false); -#endif -#else -StdInOutStream Serial = StdInOutStream(); -#endif - -#ifndef MY_SERIALDEVICE -#define MY_SERIALDEVICE Serial -#endif - -// Define these as macros (do nothing) -#define hwWatchdogReset() -#define hwReboot() -#define hwGetSleepRemaining() (0ul) - -inline void hwDigitalWrite(uint8_t, uint8_t); -inline int hwDigitalRead(uint8_t); -inline void hwPinMode(uint8_t, uint8_t); - -bool hwInit(void); -inline void hwReadConfigBlock(void *buf, void *addr, size_t length); -inline void hwWriteConfigBlock(void *buf, void *addr, size_t length); -inline uint8_t hwReadConfig(const int addr); -inline void hwWriteConfig(const int addr, uint8_t value); -inline void hwRandomNumberInit(void); -ssize_t hwGetentropy(void *__buffer, size_t __length); -#define MY_HW_HAS_GETENTROPY -inline uint32_t hwMillis(void); - -// SOFTSPI -#ifdef MY_SOFTSPI -#error Soft SPI is not available on this architecture! -#endif -#define hwSPI SPI //!< hwSPI - -#ifdef MY_RF24_IRQ_PIN -static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER; - -static __inline__ void __hwUnlock(const uint8_t *__s) -{ - pthread_mutex_unlock(&hw_mutex); - (void)__s; -} - -static __inline__ void __hwLock() -{ - pthread_mutex_lock(&hw_mutex); -} -#endif - -#if defined(DOXYGEN) -#define ATOMIC_BLOCK_CLEANUP -#elif defined(MY_RF24_IRQ_PIN) -#define ATOMIC_BLOCK_CLEANUP uint8_t __atomic_loop \ - __attribute__((__cleanup__( __hwUnlock ))) = 1 -#else -#define ATOMIC_BLOCK_CLEANUP -#endif /* DOXYGEN */ - -#if defined(DOXYGEN) -#define ATOMIC_BLOCK -#elif defined(MY_RF24_IRQ_PIN) -#define ATOMIC_BLOCK for ( ATOMIC_BLOCK_CLEANUP, __hwLock(); \ - __atomic_loop ; __atomic_loop = 0 ) -#else -#define ATOMIC_BLOCK -#endif /* DOXYGEN */ - -#ifndef DOXYGEN -#define MY_CRITICAL_SECTION ATOMIC_BLOCK -#endif /* DOXYGEN */ - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/MyMainLinuxGeneric.cpp b/lib/MySensors/hal/architecture/Linux/MyMainLinuxGeneric.cpp deleted file mode 100644 index 449ef9be..00000000 --- a/lib/MySensors/hal/architecture/Linux/MyMainLinuxGeneric.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ -// Initialize library and handle sketch functions like we want to - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "log.h" -#include "config.h" -#include "MySensorsCore.h" - -void handle_sigint(int sig) -{ - if (sig == SIGINT) { - logNotice("Received SIGINT\n\n"); - } else if (sig == SIGTERM) { - logNotice("Received SIGTERM\n\n"); - } else { - return; - } - -#ifdef MY_RF24_IRQ_PIN - detachInterrupt(MY_RF24_IRQ_PIN); -#endif - -#if defined(MY_GATEWAY_SERIAL) - MY_SERIALDEVICE.end(); -#endif - - logClose(); - - exit(EXIT_SUCCESS); -} - -static int daemonize(void) -{ - pid_t pid, sid; - - /* Fork off the parent process */ - pid = fork(); - if (pid < 0) { - logError("fork: %s\n", strerror(errno)); - return -1; - } - /* If we got a good PID, then we can exit the parent process. */ - if (pid > 0) { - exit(EXIT_SUCCESS); - } - - /* At this point we are executing as the child process */ - - /* Change the file mode mask */ - umask(0); - - /* Create a new SID for the child process */ - sid = setsid(); - if (sid < 0) { - logError("setsid: %s\n", strerror(errno)); - return -1; - } - - /* Change the current working directory. This prevents the current - directory from being locked; hence not being able to remove it. */ - if ((chdir("/")) < 0) { - logError("chdir(\"/\"): %s\n", strerror(errno)); - return -1; - } - - if (freopen( "/dev/null", "r", stdin) == NULL) { - logError("freopen: %s\n", strerror(errno)); - } - if (freopen( "/dev/null", "r", stdout) == NULL) { - logError("freopen: %s\n", strerror(errno)); - } - if (freopen( "/dev/null", "r", stderr) == NULL) { - logError("freopen: %s\n", strerror(errno)); - } - - return 0; -} - -void print_usage() -{ - printf("Usage: mysgw [options]\n\n" \ - "Options:\n" \ - " -c, --config-file Config file. [" MY_LINUX_CONFIG_FILE "]\n" \ - " -h, --help Display a short summary of all program options.\n" \ - " -q, --quiet Quiet mode, disable log messages written to the terminal.\n" \ - " --daemon Run as a daemon.\n" \ - " --gen-soft-hmac-key Generate and print a soft hmac key.\n" \ - " --gen-soft-serial-key Generate and print a soft serial key.\n" \ - " --gen-aes-key Generate and print an aes encryption key.\n"); -} - -void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL) -{ - uint8_t key[32]; - - if (key_ptr == NULL) { - hwReadConfigBlock(&key, reinterpret_castEEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); - key_ptr = key; - } - - printf("soft_hmac_key="); - for (int i = 0; i < 32; i++) { - printf("%02X", key_ptr[i]); - } - printf("\n\n"); - - printf("The next line is intended to be used in SecurityPersonalizer.ino:\n"); - printf("#define MY_HMAC_KEY "); - for (int i=0; i<32; i++) { - printf("%#02X", key_ptr[i]); - if (i < 31) { - printf(","); - } - } - printf("\n\n"); -} - -void generate_soft_sign_hmac_key(char *config_file = NULL) -{ - uint8_t key[32]; - - printf("Generating key..."); - while (hwGetentropy(&key, sizeof(key)) != sizeof(key)); - printf(" done.\n"); - - printf("To use the new key, update the value in %s witn:\n", - config_file?config_file:MY_LINUX_CONFIG_FILE); - print_soft_sign_hmac_key(key); - -#if defined(MY_SIGNING_SIMPLE_PASSWD) - printf("Note: The gateway was built with simplified signing using the password: %s\n" \ - " Any key set with soft_hmac_key option in the config file is ignored.\n\n", - MY_SIGNING_SIMPLE_PASSWD); -#elif !defined(MY_SIGNING_FEATURE) - printf("Note: The gateway was not built with signing support.\n" \ - " Any key set with soft_hmac_key option in the config file is ignored.\n\n"); -#endif -} - -void set_soft_sign_hmac_key(char *key_str) -{ - uint8_t key[32]; - - if (strlen(key_str) != 64) { - logWarning("Invalid HMAC key!\n"); - } else { - for (int i = 0; i < 64; ++i) { - int n; - char c = key_str[i]; - if (c <= '9') { - n = c - '0'; - } else if (c >= 'a') { - n = c - 'a' + 10; - } else { - n = c - 'A' + 10; - } - - if ((i & 0x1) == 0) { - key[i/2] = n * 16; - } else { - key[i/2] += n; - } - } - hwWriteConfigBlock(&key, reinterpret_castEEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); - } -} - -void print_soft_sign_serial_key(uint8_t *key_ptr = NULL) -{ - uint8_t key[9]; - - if (key_ptr == NULL) { - hwReadConfigBlock(&key, reinterpret_castEEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); - key_ptr = key; - } - - printf("soft_serial_key="); - for (int i = 0; i < 9; i++) { - printf("%02X", key_ptr[i]); - } - printf("\n\n"); - - printf("The next line is intended to be used in SecurityPersonalizer.ino:\n"); - printf("#define MY_SOFT_SERIAL "); - for (int i=0; i<9; i++) { - printf("%#02X", key_ptr[i]); - if (i < 8) { - printf(","); - } - } - printf("\n\n"); -} - -void generate_soft_sign_serial_key(char *config_file = NULL) -{ - uint8_t key[9]; - - printf("Generating key..."); - while (hwGetentropy(&key, sizeof(key)) != sizeof(key)); - printf(" done.\n"); - - printf("To use the new key, update the value in %s witn:\n", - config_file?config_file:MY_LINUX_CONFIG_FILE); - print_soft_sign_serial_key(key); - -#if defined(MY_SIGNING_SIMPLE_PASSWD) - printf("Note: The gateway was built with simplified signing using the password: %s\n" \ - " Any key set with soft_serial_key option in the config file is ignored.\n\n", - MY_SIGNING_SIMPLE_PASSWD); -#elif !defined(MY_SIGNING_FEATURE) - printf("Note: The gateway was not built with signing support.\n" \ - " Any key set with soft_serial_key option in the config file is ignored.\n\n"); -#endif -} - -void set_soft_sign_serial_key(char *key_str) -{ - uint8_t key[9]; - - if (strlen(key_str) != 18) { - logWarning("Invalid soft serial key!\n"); - } else { - for (int i = 0; i < 18; ++i) { - int n; - char c = key_str[i]; - if (c <= '9') { - n = c - '0'; - } else if (c >= 'a') { - n = c - 'a' + 10; - } else { - n = c - 'A' + 10; - } - - if ((i & 0x1) == 0) { - key[i/2] = n * 16; - } else { - key[i/2] += n; - } - } - hwWriteConfigBlock(&key, reinterpret_castEEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); - } -} - -void print_aes_key(uint8_t *key_ptr = NULL) -{ - uint8_t key[16]; - - if (key_ptr == NULL) { - hwReadConfigBlock(&key, reinterpret_castEEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); - key_ptr = key; - } - - printf("aes_key="); - for (int i = 0; i < 16; i++) { - printf("%02X", key_ptr[i]); - } - printf("\n\n"); - - printf("The next line is intended to be used in SecurityPersonalizer.ino:\n"); - printf("#define MY_AES_KEY "); - for (int i=0; i<16; i++) { - printf("%#02X", key_ptr[i]); - if (i < 15) { - printf(","); - } - } - printf("\n\n"); -} - -void generate_aes_key(char *config_file = NULL) -{ - uint8_t key[16]; - - printf("Generating key..."); - while (hwGetentropy(&key, sizeof(key)) != sizeof(key)); - printf(" done.\n"); - - printf("To use the new key, update the value in %s witn:\n", - config_file?config_file:MY_LINUX_CONFIG_FILE); - print_aes_key(key); - -#if defined(MY_ENCRYPTION_SIMPLE_PASSWD) - printf("Note: The gateway was built with simplified encryption using the password: %s\n" \ - " Any key set with aes_key option in the config file is ignored.\n\n", - MY_ENCRYPTION_SIMPLE_PASSWD); -#elif !defined(MY_ENCRYPTION_FEATURE) - printf("Note: The gateway was not built with encryption support.\n" \ - " Any key set with aes_key option in the config file is ignored.\n\n"); -#endif -} - -void set_aes_key(char *key_str) -{ - uint8_t key[16]; - - if (strlen(key_str) != 32) { - logWarning("Invalid AES key!\n"); - } else { - for (int i = 0; i < 32; ++i) { - int n; - char c = key_str[i]; - if (c <= '9') { - n = c - '0'; - } else if (c >= 'a') { - n = c - 'a' + 10; - } else { - n = c - 'A' + 10; - } - - if ((i & 0x1) == 0) { - key[i/2] = n * 16; - } else { - key[i/2] += n; - } - } - hwWriteConfigBlock(&key, reinterpret_castEEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); - } -} - -int main(int argc, char *argv[]) -{ - int opt, daemon = 0, quiet = 0; - char *config_file = NULL; - bool gen_soft_sign_hmac_key = false; - bool gen_soft_sign_serial_key = false; - bool gen_aes_key = false; - - /* register the signal handler */ - signal(SIGINT, handle_sigint); - signal(SIGTERM, handle_sigint); - signal(SIGPIPE, handle_sigint); - - hwRandomNumberInit(); - - static struct option long_options[] = { - {"config-file", required_argument, 0, 'c'}, - {"daemon", no_argument, 0, 'J'}, - {"help", no_argument, 0, 'h'}, - {"quiet", no_argument, 0, 'q'}, - {"gen-soft-hmac-key", no_argument, 0, 'A'}, - {"gen-soft-serial-key", no_argument, 0, 'B'}, - {"gen-aes-key", no_argument, 0, 'C'}, - {0, 0, 0, 0} - }; - - int long_index = 0; - while ((opt = getopt_long(argc, argv,"chqABCJ", long_options, &long_index )) != -1) { - switch (opt) { - case 'c': - config_file = strdup(optarg); - break; - case 'h': - print_usage(); - exit(EXIT_SUCCESS); - case 'q': - quiet = 1; - break; - case 'A': - gen_soft_sign_hmac_key = true; - break; - case 'B': - gen_soft_sign_serial_key = true; - break; - case 'C': - gen_aes_key = true; - break; - case 'J': - daemon = 1; - break; - default: - print_usage(); - exit(EXIT_SUCCESS); - } - } - - if (gen_soft_sign_hmac_key || gen_soft_sign_serial_key || gen_aes_key) { - if (gen_soft_sign_hmac_key) { - generate_soft_sign_hmac_key(config_file); - } - if (gen_soft_sign_serial_key) { - generate_soft_sign_serial_key(config_file); - } - if (gen_aes_key) { - generate_aes_key(config_file); - } - exit(EXIT_SUCCESS); - } - - if (daemon) { - if (daemonize() != 0) { - exit(EXIT_FAILURE); - } - quiet = 1; - } - - if (config_parse(config_file?config_file:MY_LINUX_CONFIG_FILE) != 0) { - exit(EXIT_FAILURE); - } - - logSetQuiet(quiet); - logSetLevel(conf.verbose); - - if (conf.log_file) { - if (logSetFile(conf.log_filepath) != 0) { - logError("Failed to open log file.\n"); - } - } - - if (conf.log_pipe) { - if (logSetPipe(conf.log_pipe_file) != 0) { - logError("Failed to open log pipe.\n"); - } - } - - if (conf.syslog) { - logSetSyslog(LOG_CONS, LOG_USER); - } - - logInfo("Starting gateway...\n"); - logInfo("Protocol version - %s\n", MYSENSORS_LIBRARY_VERSION); - - _begin(); // Startup MySensors library - - // EEPROM is initialized within _begin() - // any operation on it must be done hereafter - -#if defined(MY_SIGNING_FEATURE) && !defined(MY_SIGNING_SIMPLE_PASSWD) - // Check if we need to update the signing keys in EEPROM - if (conf.soft_hmac_key) { - set_soft_sign_hmac_key(conf.soft_hmac_key); - } else { - logError("soft_hmac_key was not found in %s\n", config_file?config_file:MY_LINUX_CONFIG_FILE); - exit(EXIT_FAILURE); - } - if (conf.soft_serial_key) { - set_soft_sign_serial_key(conf.soft_serial_key); - } else { - logError("soft_serial_key was not found in %s\n", config_file?config_file:MY_LINUX_CONFIG_FILE); - exit(EXIT_FAILURE); - } -#endif -#if defined(MY_ENCRYPTION_FEATURE) && !defined(MY_ENCRYPTION_SIMPLE_PASSWD) - // Check if we need to update the encryption key in EEPROM - if (conf.aes_key) { - set_aes_key(conf.aes_key); - } else { - logError("aes_key was not found in %s\n", config_file?config_file:MY_LINUX_CONFIG_FILE); - exit(EXIT_FAILURE); - } -#endif - - if (config_file) { - free(config_file); - } - - for (;;) { - _process(); // Process incoming data - if (loop) { - loop(); // Call sketch loop - } - } - return 0; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/BCM.cpp b/lib/MySensors/hal/architecture/Linux/drivers/BCM/BCM.cpp deleted file mode 100644 index 5a681082..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/BCM.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "BCM.h" -#include -#include "log.h" - -// Declare a single default instance -BCMClass BCM = BCMClass(); - -uint8_t BCMClass::initialized = 0; - -BCMClass::~BCMClass() -{ - if (initialized) { - bcm2835_close(); - initialized = 0; - } -} - -uint8_t BCMClass::init() -{ - if (!bcm2835_init()) { - logError("Failed to initialized bcm2835.\n"); - exit(1); - } - initialized = 1; - - return 1; -} - -void BCMClass::pinMode(uint8_t gpio, uint8_t mode) -{ - if (!initialized) { - init(); - } - - bcm2835_gpio_fsel(gpio, mode); -} - -void BCMClass::digitalWrite(uint8_t gpio, uint8_t value) -{ - if (!initialized) { - init(); - } - - bcm2835_gpio_write(gpio, value); - // Delay to allow any change in state to be reflected in the LEVn, register bit. - delayMicroseconds(1); -} - -uint8_t BCMClass::digitalRead(uint8_t gpio) -{ - if (!initialized) { - init(); - } - - return bcm2835_gpio_lev(gpio); -} - -uint8_t BCMClass::isInitialized() -{ - return initialized; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/BCM.h b/lib/MySensors/hal/architecture/Linux/drivers/BCM/BCM.h deleted file mode 100644 index 31d42fe9..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/BCM.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef BCM_h -#define BCM_h - -#include -#include "bcm2835.h" - -#define INPUT BCM2835_GPIO_FSEL_INPT -#define OUTPUT BCM2835_GPIO_FSEL_OUTP - -/** - * @brief BCM class - */ -class BCMClass -{ - -public: - /** - * @brief BCMClass destructor. - */ - ~BCMClass(); - /** - * @brief Initializes BCM. - * - * @return 1 if successful, else exits the program. - */ - uint8_t init(); - /** - * @brief Configures the specified pin to behave either as an input or an output. - * - * @param gpio The GPIO pin number. - * @param mode INPUT or OUTPUT. - */ - void pinMode(uint8_t gpio, uint8_t mode); - /** - * @brief Write a high or a low value for the given pin. - * - * @param gpio The GPIO pin number. - * @param value HIGH or LOW. - */ - void digitalWrite(uint8_t gpio, uint8_t value); - /** - * @brief Reads the value from a specified pin. - * - * @param gpio The GPIO pin number. - * @return HIGH or LOW. - */ - uint8_t digitalRead(uint8_t gpio); - /** - * @brief Returns the same GPIO, no conversion is required. - * - * @param gpio The GPIO pin number. - * @return The GPIO pin number. - */ - inline uint8_t digitalPinToInterrupt(uint8_t gpio); - /** - * @brief Checks if SPI was initialized. - * - * @return 1 if initialized, else 0. - */ - uint8_t isInitialized(); - -private: - static uint8_t initialized; //!< @brief BCM initialized flag. -}; - -uint8_t BCMClass::digitalPinToInterrupt(uint8_t gpio) -{ - return gpio; -} - -extern BCMClass BCM; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/RPi.cpp b/lib/MySensors/hal/architecture/Linux/drivers/BCM/RPi.cpp deleted file mode 100644 index 2aa2189a..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/RPi.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "RPi.h" -#include -#include -#include -#include -#include "log.h" - -const static int phys_to_gpio_rev1[41] = {-1, -1, -1, 0, -1, 1, -1, 4, 14, -1, 15, 17, 18, 21, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; -const static int phys_to_gpio_rev2[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, 5, -1, 6, 12, 13, -1, 19, 16, 26, 20, -1, 21}; - -// Declare a single default instance -RPiClass RPi = RPiClass(); - -const int* RPiClass::phys_to_gpio = NULL; - -void RPiClass::pinMode(uint8_t physPin, uint8_t mode) -{ - uint8_t gpioPin; - - if (physToGPIO(physPin, &gpioPin) != 0) { - logError("pinMode: invalid pin: %d\n", physPin); - return; - } - - BCM.pinMode(gpioPin, mode); -} - -void RPiClass::digitalWrite(uint8_t physPin, uint8_t value) -{ - uint8_t gpioPin; - - if (physToGPIO(physPin, &gpioPin) != 0) { - logError("digitalWrite: invalid pin: %d\n", physPin); - return; - } - - BCM.digitalWrite(gpioPin, value); -} - -uint8_t RPiClass::digitalRead(uint8_t physPin) -{ - uint8_t gpioPin; - - if (physToGPIO(physPin, &gpioPin) != 0) { - logError("digitalRead: invalid pin: %d\n", physPin); - return 0; - } - - return BCM.digitalRead(gpioPin); -} - -uint8_t RPiClass::digitalPinToInterrupt(uint8_t physPin) -{ - uint8_t gpioPin; - - if (physToGPIO(physPin, &gpioPin) != 0) { - logError("digitalPinToInterrupt: invalid pin: %d\n", physPin); - return 0; - } - - return gpioPin; -} - -int RPiClass::rpiGpioLayout() -{ - /* - * Based on wiringPi Copyright (c) 2012 Gordon Henderson. - */ - FILE *fd; - char line[120]; - char *c; - - if ((fd = fopen("/proc/cpuinfo", "r")) == NULL) { - return -1; - } - - while (fgets(line, 120, fd) != NULL) { - if (strncmp(line, "Revision", 8) == 0) { - fclose(fd); - // Chop trailing CR/NL - for (c = &line[strlen(line) - 1]; (*c == '\n') || (*c == '\r'); --c) { - *c = 0; - } - // Scan to the first character of the revision number - for (c = line; *c; ++c) { - if (*c == ':') { - // Chop spaces - ++c; - while (isspace(*c)) { - ++c; - } - - // Check hex digit at start - if (!isxdigit(*c)) { - return -1; - } - - // Check bogus revision line (too small) - if (strlen(c) < 4) { - return -1; - } - - // Isolate last 4 characters: (in-case of overvolting or new encoding scheme) - c = c + strlen(c) - 4; - - if ((strcmp(c, "0002") == 0) || (strcmp(c, "0003") == 0) || - (strcmp(c, "0004") == 0) || (strcmp(c, "0005") == 0) || - (strcmp(c, "0006") == 0) || (strcmp(c, "0007") == 0) || - (strcmp(c, "0008") == 0) || (strcmp(c, "0009") == 0) || - (strcmp(c, "000d") == 0) || (strcmp(c, "000e") == 0) || - (strcmp(c, "000f") == 0)) { - return 1; - } else { - return 2; - } - } - } - } - } - fclose(fd); - return -1; -} - -int RPiClass::physToGPIO(uint8_t physPin, uint8_t *gpio) -{ - if (phys_to_gpio == NULL) { - if (rpiGpioLayout() == 1) { - // A, B, Rev 1, 1.1 - phys_to_gpio = &phys_to_gpio_rev1[0]; - } else { - // A2, B2, A+, B+, CM, Pi2, Pi3, Zero - phys_to_gpio = &phys_to_gpio_rev2[0]; - } - } - - if (gpio == NULL || physPin > 40) { - return -1; - } - - int pin = *(phys_to_gpio+physPin); - if (pin == -1) { - return -1; - } else { - *gpio = pin; - } - - return 0; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/RPi.h b/lib/MySensors/hal/architecture/Linux/drivers/BCM/RPi.h deleted file mode 100644 index 14e8c96a..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/RPi.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef RPi_h -#define RPi_h - -#include -#include "BCM.h" - -/** - * @brief RPi class - */ -class RPiClass -{ - -public: - /** - * @brief Configures the specified pin to behave either as an input or an output. - * - * @param physPin The physical number of the pin. - * @param mode INPUT or OUTPUT. - */ - void pinMode(uint8_t physPin, uint8_t mode); - /** - * @brief Write a high or a low value for the given pin. - * - * @param physPin The physical number of the pin. - * @param value HIGH or LOW. - */ - void digitalWrite(uint8_t physPin, uint8_t value); - /** - * @brief Reads the value from a specified pin. - * - * @param physPin The physical number of the pin. - * @return HIGH or LOW. - */ - uint8_t digitalRead(uint8_t physPin); - /** - * @brief Translate the physical pin number to the GPIO number for use in interrupt. - * - * @param physPin The physical number of the pin. - * @return The GPIO pin number. - */ - uint8_t digitalPinToInterrupt(uint8_t physPin); - /** - * @brief Translate the physical pin number to the GPIO number. - * - * @param physPin The physical number of the pin. - * @param gpio Pointer to write the GPIO pin number when success. - * @return -1 if FAILURE or 0 if SUCCESS. - */ - static int physToGPIO(uint8_t physPin, uint8_t *gpio); - -private: - static const int *phys_to_gpio; //!< @brief Pointer to array of GPIO pins numbers. - /** - * @brief Get the gpio layout. - * - * @return The gpio layout number. - */ - static int rpiGpioLayout(void); -}; - -extern RPiClass RPi; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/SPIBCM.cpp b/lib/MySensors/hal/architecture/Linux/drivers/BCM/SPIBCM.cpp deleted file mode 100644 index 9bbfae4d..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/SPIBCM.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on TMRh20 RF24 library, Copyright (c) 2015 Charles-Henri Hallard - */ - -#include "SPIBCM.h" -#include -#include -#include "log.h" - -static pthread_mutex_t spiMutex = PTHREAD_MUTEX_INITIALIZER; - -// Declare a single default instance -SPIBCMClass SPIBCM = SPIBCMClass(); - -uint8_t SPIBCMClass::initialized = 0; - -void SPIBCMClass::begin() -{ - if (!initialized) { - if (!BCM.isInitialized()) { - BCM.init(); - } - if (!bcm2835_spi_begin()) { - logError("You need root privilege to use SPI.\n"); - exit(1); - } - } - - initialized++; // reference count -} - -void SPIBCMClass::end() -{ - if (initialized) { - initialized--; - } - - if (!initialized) { - // End the SPI - bcm2835_spi_end(); - } -} - -void SPIBCMClass::setBitOrder(uint8_t bit_order) -{ - bcm2835_spi_setBitOrder(bit_order); -} - -void SPIBCMClass::setDataMode(uint8_t data_mode) -{ - bcm2835_spi_setDataMode(data_mode); -} - -void SPIBCMClass::setClockDivider(uint16_t divider) -{ - bcm2835_spi_setClockDivider(divider); -} - -void SPIBCMClass::chipSelect(int csn_pin) -{ - if (csn_pin == RPI_GPIO_P1_26) { - csn_pin = BCM2835_SPI_CS1; - } else if (csn_pin == RPI_GPIO_P1_24) { - csn_pin = BCM2835_SPI_CS0; - } else { - csn_pin = BCM2835_SPI_CS0; - } - bcm2835_spi_chipSelect(csn_pin); - delayMicroseconds(5); -} - -void SPIBCMClass::beginTransaction(SPISettings settings) -{ - pthread_mutex_lock(&spiMutex); - setBitOrder(settings.border); - setDataMode(settings.dmode); - setClockDivider(settings.cdiv); -} - -void SPIBCMClass::endTransaction() -{ - pthread_mutex_unlock(&spiMutex); -} - -void SPIBCMClass::usingInterrupt(uint8_t interruptNumber) -{ - (void)interruptNumber; -} - -void SPIBCMClass::notUsingInterrupt(uint8_t interruptNumber) -{ - (void)interruptNumber; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/SPIBCM.h b/lib/MySensors/hal/architecture/Linux/drivers/BCM/SPIBCM.h deleted file mode 100644 index 38c9ec84..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/SPIBCM.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on TMRh20 RF24 library, Copyright (c) 2015 Charles-Henri Hallard - */ - -#ifndef SPIBCM_h -#define SPIBCM_h - -#include -#include "bcm2835.h" -#include "BCM.h" - -#define SPI_HAS_TRANSACTION - -#define SPI_CLOCK_BASE 256000000 - -// SPI Clock divider -#define SPI_CLOCK_DIV1 BCM2835_SPI_CLOCK_DIVIDER_1 -#define SPI_CLOCK_DIV2 BCM2835_SPI_CLOCK_DIVIDER_2 -#define SPI_CLOCK_DIV4 BCM2835_SPI_CLOCK_DIVIDER_4 -#define SPI_CLOCK_DIV8 BCM2835_SPI_CLOCK_DIVIDER_8 -#define SPI_CLOCK_DIV16 BCM2835_SPI_CLOCK_DIVIDER_16 -#define SPI_CLOCK_DIV32 BCM2835_SPI_CLOCK_DIVIDER_32 -#define SPI_CLOCK_DIV64 BCM2835_SPI_CLOCK_DIVIDER_64 -#define SPI_CLOCK_DIV128 BCM2835_SPI_CLOCK_DIVIDER_128 -#define SPI_CLOCK_DIV256 BCM2835_SPI_CLOCK_DIVIDER_256 -#define SPI_CLOCK_DIV512 BCM2835_SPI_CLOCK_DIVIDER_512 -#define SPI_CLOCK_DIV1024 BCM2835_SPI_CLOCK_DIVIDER_1024 -#define SPI_CLOCK_DIV2048 BCM2835_SPI_CLOCK_DIVIDER_2048 -#define SPI_CLOCK_DIV4096 BCM2835_SPI_CLOCK_DIVIDER_4096 -#define SPI_CLOCK_DIV8192 BCM2835_SPI_CLOCK_DIVIDER_8192 -#define SPI_CLOCK_DIV16384 BCM2835_SPI_CLOCK_DIVIDER_16384 -#define SPI_CLOCK_DIV32768 BCM2835_SPI_CLOCK_DIVIDER_32768 -#define SPI_CLOCK_DIV65536 BCM2835_SPI_CLOCK_DIVIDER_65536 - -// SPI Data mode -#define SPI_MODE0 BCM2835_SPI_MODE0 -#define SPI_MODE1 BCM2835_SPI_MODE1 -#define SPI_MODE2 BCM2835_SPI_MODE2 -#define SPI_MODE3 BCM2835_SPI_MODE3 - -#define LSBFIRST BCM2835_SPI_BIT_ORDER_LSBFIRST -#define MSBFIRST BCM2835_SPI_BIT_ORDER_MSBFIRST - -const uint8_t SS = 24; -const uint8_t MOSI = 19; -const uint8_t MISO = 21; -const uint8_t SCK = 23; - -/** - * SPISettings class - */ -class SPISettings -{ - -public: - /** - * @brief SPISettings constructor. - * - * Default clock speed is 8Mhz. - */ - SPISettings() - { - init(SPI_CLOCK_DIV32, MSBFIRST, SPI_MODE0); - } - /** - * @brief SPISettings constructor. - * - * @param clock SPI clock speed in Hz. - * @param bitOrder SPI bit order. - * @param dataMode SPI data mode. - */ - SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) - { - uint16_t divider; - - if (clock >= SPI_CLOCK_BASE) { - divider = SPI_CLOCK_DIV1; - } else if (clock >= SPI_CLOCK_BASE / 2) { - divider = SPI_CLOCK_DIV2; - } else if (clock >= SPI_CLOCK_BASE / 4) { - divider = SPI_CLOCK_DIV4; - } else if (clock >= SPI_CLOCK_BASE / 8) { - divider = SPI_CLOCK_DIV8; - } else if (clock >= SPI_CLOCK_BASE / 16) { - divider = SPI_CLOCK_DIV16; - } else if (clock >= SPI_CLOCK_BASE / 32) { - divider = SPI_CLOCK_DIV32; - } else if (clock >= SPI_CLOCK_BASE / 64) { - divider = SPI_CLOCK_DIV64; - } else if (clock >= SPI_CLOCK_BASE / 128) { - divider = SPI_CLOCK_DIV128; - } else if (clock >= SPI_CLOCK_BASE / 256) { - divider = SPI_CLOCK_DIV256; - } else if (clock >= SPI_CLOCK_BASE / 512) { - divider = SPI_CLOCK_DIV512; - } else if (clock >= SPI_CLOCK_BASE / 1024) { - divider = SPI_CLOCK_DIV1024; - } else if (clock >= SPI_CLOCK_BASE / 2048) { - divider = SPI_CLOCK_DIV2048; - } else if (clock >= SPI_CLOCK_BASE / 4096) { - divider = SPI_CLOCK_DIV4096; - } else if (clock >= SPI_CLOCK_BASE / 8192) { - divider = SPI_CLOCK_DIV8192; - } else if (clock >= SPI_CLOCK_BASE / 16384) { - divider = SPI_CLOCK_DIV16384; - } else if (clock >= SPI_CLOCK_BASE / 32768) { - divider = SPI_CLOCK_DIV32768; - } else if (clock >= SPI_CLOCK_BASE / 65536) { - divider = SPI_CLOCK_DIV65536; - } else { - // Default to 8Mhz - divider = SPI_CLOCK_DIV32; - } - - init(divider, bitOrder, dataMode); - } - - uint16_t cdiv; //!< @brief SPI clock divider. - uint8_t border; //!< @brief SPI bit order. - uint8_t dmode; //!< @brief SPI data mode. - -private: - /** - * @brief Initialized class members. - * - * @param divider SPI clock divider. - * @param bitOrder SPI bit order. - * @param dataMode SPI data mode. - */ - void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode) - { - cdiv = divider; - border = bitOrder; - dmode = dataMode; - } - - friend class SPIBCMClass; -}; - -/** - * SPIBCM class - */ -class SPIBCMClass -{ - -public: - /** - * @brief Send and receive a byte. - * - * @param data to send. - * @return byte received. - */ - inline static uint8_t transfer(uint8_t data); - /** - * @brief Send and receive a number of bytes. - * - * @param tbuf Sending buffer. - * @param rbuf Receive buffer. - * @param len Buffer length. - */ - inline static void transfernb(char* tbuf, char* rbuf, uint32_t len); - /** - * @brief Send and receive a number of bytes. - * - * @param buf Buffer to read from and write to. - * @param len Buffer length. - */ - inline static void transfern(char* buf, uint32_t len); - /** - * @brief Start SPI operations. - */ - static void begin(); - /** - * @brief End SPI operations. - */ - static void end(); - /** - * @brief Sets the SPI bit order. - * - * @param bit_order The desired bit order. - */ - static void setBitOrder(uint8_t bit_order); - /** - * @brief Sets the SPI data mode. - * - * @param data_mode The desired data mode. - */ - static void setDataMode(uint8_t data_mode); - /** - * @brief Sets the SPI clock divider and therefore the SPI clock speed. - * - * @param divider The desired SPI clock divider. - */ - static void setClockDivider(uint16_t divider); - /** - * @brief Sets the chip select pin. - * - * @param csn_pin Specifies the CS pin. - */ - static void chipSelect(int csn_pin); - /** - * @brief Start SPI transaction. - * - * @param settings for SPI. - */ - static void beginTransaction(SPISettings settings); - /** - * @brief End SPI transaction. - */ - static void endTransaction(); - /** - * @brief Not implemented. - * - * @param interruptNumber ignored parameter. - */ - static void usingInterrupt(uint8_t interruptNumber); - /** - * @brief Not implemented. - * - * @param interruptNumber ignored parameter. - */ - static void notUsingInterrupt(uint8_t interruptNumber); - -private: - static uint8_t initialized; //!< @brief SPI initialized flag. -}; - -uint8_t SPIBCMClass::transfer(uint8_t data) -{ - return bcm2835_spi_transfer(data); -} - -void SPIBCMClass::transfernb(char* tbuf, char* rbuf, uint32_t len) -{ - bcm2835_spi_transfernb( tbuf, rbuf, len); -} - -void SPIBCMClass::transfern(char* buf, uint32_t len) -{ - transfernb(buf, buf, len); -} - -extern SPIBCMClass SPIBCM; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/Wire.cpp b/lib/MySensors/hal/architecture/Linux/drivers/BCM/Wire.cpp deleted file mode 100644 index eeb487f0..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/Wire.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - TwoWire.h - TWI/I2C library for Arduino & Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - 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 - - Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts - Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support - Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support - Modified October 2016 by Marcelo Aquino for Raspberry Pi -*/ - -#include "Wire.h" -#include -#include -#include "bcm2835.h" -#include "log.h" - -static pthread_mutex_t i2cMutex = PTHREAD_MUTEX_INITIALIZER; - -uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::rxBufferIndex = 0; -uint8_t TwoWire::rxBufferLength = 0; - -uint8_t TwoWire::txAddress = 0; -uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::txBufferIndex = 0; -uint8_t TwoWire::txBufferLength = 0; - -uint8_t TwoWire::transmitting = 0; - -void TwoWire::begin() -{ - if (!bcm2835_i2c_begin()) { - logError("You need root privilege to use I2C.\n"); - exit(1); - } -} - -void TwoWire::begin(uint8_t address) -{ - begin(); - bcm2835_i2c_setSlaveAddress(address); -} - -void TwoWire::begin(int address) -{ - begin(static_cast(address)); -} - -void TwoWire::end() -{ - bcm2835_i2c_end(); -} - -void TwoWire::setClock(uint32_t clock) -{ - bcm2835_i2c_set_baudrate(clock); -} - -void TwoWire::beginTransmission(uint8_t address) -{ - pthread_mutex_lock(&i2cMutex); - // indicate that we are transmitting - transmitting = 1; - // set address of targeted slave - txAddress = address; - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; -} - -void TwoWire::beginTransmission(int address) -{ - beginTransmission(static_cast(address)); -} - -uint8_t TwoWire::endTransmission(void) -{ - // transmit buffer - bcm2835_i2c_setSlaveAddress(txAddress); - uint8_t ret = bcm2835_i2c_write(reinterpret_cast(txBuffer), txBufferLength); - - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; - // indicate that we are done transmitting - transmitting = 0; - - pthread_mutex_unlock(&i2cMutex); - - if (ret == BCM2835_I2C_REASON_OK) { - return 0; // success - } else if (ret == BCM2835_I2C_REASON_ERROR_NACK) { - return 3; // error: data send, nack received - } - return 4; // other error -} - -size_t TwoWire::requestFrom(uint8_t address, size_t quantity) -{ - // clamp to buffer length - if (quantity > BUFFER_LENGTH) { - quantity = BUFFER_LENGTH; - } - - rxBufferIndex = 0; - rxBufferLength = 0; - - bcm2835_i2c_setSlaveAddress(address); - uint8_t ret = bcm2835_i2c_read(reinterpret_cast(rxBuffer), quantity); - if (ret == BCM2835_I2C_REASON_OK) { - rxBufferLength = quantity; - } - - return rxBufferLength; -} - -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) -{ - return requestFrom(address, static_cast(quantity)); -} - -uint8_t TwoWire::requestFrom(int address, int quantity) -{ - return requestFrom(static_cast(address), static_cast(quantity)); -} - -size_t TwoWire::write(uint8_t data) -{ - if (transmitting) { - // in master transmitter mode - // don't bother if buffer is full - if (txBufferLength >= BUFFER_LENGTH) { - setWriteError(); - return 0; - } - // put byte in tx buffer - txBuffer[txBufferIndex] = data; - ++txBufferIndex; - // update amount in buffer - txBufferLength = txBufferIndex; - - return 1; - } else { - return write(&data, 1); - } -} - -size_t TwoWire::write(const uint8_t *data, size_t quantity) -{ - if (transmitting) { - // in master transmitter mode - for (size_t i = 0; i < quantity; ++i) { - write(data[i]); - } - } else { - uint8_t rc = bcm2835_i2c_write(reinterpret_cast(data), quantity); - if (rc != BCM2835_I2C_REASON_OK) { - return 0; - } - } - - return quantity; -} - -int TwoWire::available() -{ - return rxBufferLength - rxBufferIndex; -} - -int TwoWire::read() -{ - int value = -1; - - if (rxBufferIndex < rxBufferLength) { - value = rxBuffer[rxBufferIndex]; - ++rxBufferIndex; - } - - return value; -} - -int TwoWire::peek() -{ - if (rxBufferIndex < rxBufferLength) { - return rxBuffer[rxBufferIndex]; - } - - return -1; -} - -void TwoWire::flush() -{ - rxBufferIndex = 0; - rxBufferLength = 0; - txBufferIndex = 0; - txBufferLength = 0; -} - -TwoWire Wire = TwoWire(); diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/Wire.h b/lib/MySensors/hal/architecture/Linux/drivers/BCM/Wire.h deleted file mode 100644 index 3b129da4..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/Wire.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - TwoWire.h - TWI/I2C library for Arduino & Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - 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 - - Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts - Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support - Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support - Modified October 2016 by Marcelo Aquino for Raspberry Pi -*/ - -#ifndef Wire_h -#define Wire_h - -#if !DOXYGEN -#include -#include "Stream.h" -#include "BCM.h" - -#define BUFFER_LENGTH 32 - -class TwoWire : public Stream -{ - -private: - static uint8_t rxBuffer[]; - static uint8_t rxBufferIndex; - static uint8_t rxBufferLength; - - static uint8_t txAddress; - static uint8_t txBuffer[]; - static uint8_t txBufferIndex; - static uint8_t txBufferLength; - - static uint8_t transmitting; - -public: - void begin(); - void begin(uint8_t address); - void begin(int address); - void end(); - void setClock(uint32_t clock); - - void beginTransmission(uint8_t address); - void beginTransmission(int address); - uint8_t endTransmission(void); - - size_t requestFrom(uint8_t address, size_t size); - uint8_t requestFrom(uint8_t address, uint8_t quantity); - uint8_t requestFrom(int address, int quantity); - - size_t write(uint8_t data); - size_t write(const uint8_t *data, size_t quantity); - int available(); - int read(); - int peek(); - void flush(); - - inline size_t write(unsigned long n) - { - return write((uint8_t)n); - } - inline size_t write(long n) - { - return write((uint8_t)n); - } - inline size_t write(unsigned int n) - { - return write((uint8_t)n); - } - inline size_t write(int n) - { - return write((uint8_t)n); - } - using Print::write; -}; - -extern TwoWire Wire; - -#endif -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/bcm2835.c b/lib/MySensors/hal/architecture/Linux/drivers/BCM/bcm2835.c deleted file mode 100644 index 425d1e01..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/bcm2835.c +++ /dev/null @@ -1,1948 +0,0 @@ -/* bcm2835.c -// C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi -// http://elinux.org/RPi_Low-level_peripherals -// http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf -// -// Author: Mike McCauley -// Copyright (C) 2011-2013 Mike McCauley -// $Id: bcm2835.c,v 1.27 2019/07/22 23:04:24 mikem Exp mikem $ -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BCK2835_LIBRARY_BUILD -#include "bcm2835.h" - -/* This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11) -// You can do some safe, non-destructive testing on any platform with: -// gcc bcm2835.c -D BCM2835_TEST -// ./a.out -*/ -/*#define BCM2835_TEST*/ - -/* Uncommenting this define compiles alternative I2C code for the version 1 RPi -// The P1 header I2C pins are connected to SDA0 and SCL0 on V1. -// By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. -*/ -/* #define I2C_V1*/ - -/* Physical address and size of the peripherals block -// May be overridden on RPi2 -*/ -uint32_t *bcm2835_peripherals_base = (uint32_t *)BCM2835_PERI_BASE; -uint32_t bcm2835_peripherals_size = BCM2835_PERI_SIZE; - -/* Virtual memory address of the mapped peripherals block - */ -uint32_t *bcm2835_peripherals = (uint32_t *)MAP_FAILED; - -/* And the register bases within the peripherals block - */ -volatile uint32_t *bcm2835_gpio = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_pwm = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_clk = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_pads = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_spi0 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_bsc0 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_bsc1 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_st = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_aux = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_spi1 = (uint32_t *)MAP_FAILED; - - - -/* This variable allows us to test on hardware other than RPi. -// It prevents access to the kernel memory, and does not do any peripheral access -// Instead it prints out what it _would_ do if debug were 0 - */ -static uint8_t debug = 0; - -/* RPI 4 has different pullup registers - we need to know if we have that type */ - -static uint8_t pud_type_rpi4 = 0; - -/* RPI 4 has different pullup operation - make backwards compat */ - -static uint8_t pud_compat_setting = BCM2835_GPIO_PUD_OFF; - -/* I2C The time needed to transmit one byte. In microseconds. - */ -static int i2c_byte_wait_us = 0; - -/* SPI bit order. BCM2835 SPI0 only supports MSBFIRST, so we instead - * have a software based bit reversal, based on a contribution by Damiano Benedetti - */ -static uint8_t bcm2835_spi_bit_order = BCM2835_SPI_BIT_ORDER_MSBFIRST; -static uint8_t bcm2835_byte_reverse_table[] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff -}; - -static uint8_t bcm2835_correct_order(uint8_t b) -{ - if (bcm2835_spi_bit_order == BCM2835_SPI_BIT_ORDER_LSBFIRST) { - return bcm2835_byte_reverse_table[b]; - } else { - return b; - } -} - -/* -// Low level register access functions -*/ - -/* Function to return the pointers to the hardware register bases */ -uint32_t* bcm2835_regbase(uint8_t regbase) -{ - switch (regbase) { - case BCM2835_REGBASE_ST: - return (uint32_t *)bcm2835_st; - case BCM2835_REGBASE_GPIO: - return (uint32_t *)bcm2835_gpio; - case BCM2835_REGBASE_PWM: - return (uint32_t *)bcm2835_pwm; - case BCM2835_REGBASE_CLK: - return (uint32_t *)bcm2835_clk; - case BCM2835_REGBASE_PADS: - return (uint32_t *)bcm2835_pads; - case BCM2835_REGBASE_SPI0: - return (uint32_t *)bcm2835_spi0; - case BCM2835_REGBASE_BSC0: - return (uint32_t *)bcm2835_bsc0; - case BCM2835_REGBASE_BSC1: - return (uint32_t *)bcm2835_st; - case BCM2835_REGBASE_AUX: - return (uint32_t *)bcm2835_aux; - case BCM2835_REGBASE_SPI1: - return (uint32_t *)bcm2835_spi1; - - } - return (uint32_t *)MAP_FAILED; -} - -void bcm2835_set_debug(uint8_t d) -{ - debug = d; -} - -unsigned int bcm2835_version(void) -{ - return BCM2835_VERSION; -} - -/* Read with memory barriers from peripheral - * - */ -uint32_t bcm2835_peri_read(volatile uint32_t* paddr) -{ - uint32_t ret; - if (debug) { - printf("bcm2835_peri_read paddr %p\n", (void *) paddr); - return 0; - } else { - __sync_synchronize(); - ret = *paddr; - __sync_synchronize(); - return ret; - } -} - -/* read from peripheral without the read barrier - * This can only be used if more reads to THE SAME peripheral - * will follow. The sequence must terminate with memory barrier - * before any read or write to another peripheral can occur. - * The MB can be explicit, or one of the barrier read/write calls. - */ -uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) -{ - if (debug) { - printf("bcm2835_peri_read_nb paddr %p\n", paddr); - return 0; - } else { - return *paddr; - } -} - -/* Write with memory barriers to peripheral - */ - -void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) -{ - if (debug) { - printf("bcm2835_peri_write paddr %p, value %08X\n", paddr, value); - } else { - __sync_synchronize(); - *paddr = value; - __sync_synchronize(); - } -} - -/* write to peripheral without the write barrier */ -void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) -{ - if (debug) { - printf("bcm2835_peri_write_nb paddr %p, value %08X\n", - paddr, value); - } else { - *paddr = value; - } -} - -/* Set/clear only the bits in value covered by the mask - * This is not atomic - can be interrupted. - */ -void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask) -{ - uint32_t v = bcm2835_peri_read(paddr); - v = (v & ~mask) | (value & mask); - bcm2835_peri_write(paddr, v); -} - -/* -// Low level convenience functions -*/ - -/* Function select -// pin is a BCM2835 GPIO pin number NOT RPi pin number -// There are 6 control registers, each control the functions of a block -// of 10 pins. -// Each control register has 10 sets of 3 bits per GPIO pin: -// -// 000 = GPIO Pin X is an input -// 001 = GPIO Pin X is an output -// 100 = GPIO Pin X takes alternate function 0 -// 101 = GPIO Pin X takes alternate function 1 -// 110 = GPIO Pin X takes alternate function 2 -// 111 = GPIO Pin X takes alternate function 3 -// 011 = GPIO Pin X takes alternate function 4 -// 010 = GPIO Pin X takes alternate function 5 -// -// So the 3 bits for port X are: -// X / 10 + ((X % 10) * 3) -*/ -void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) -{ - /* Function selects are 10 pins per 32 bit word, 3 bits per pin */ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10); - uint8_t shift = (pin % 10) * 3; - uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; - uint32_t value = mode << shift; - bcm2835_peri_set_bits(paddr, value, mask); -} - -/* Set output pin */ -void bcm2835_gpio_set(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, 1 << shift); -} - -/* Clear output pin */ -void bcm2835_gpio_clr(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, 1 << shift); -} - -/* Set all output pins in the mask */ -void bcm2835_gpio_set_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4; - bcm2835_peri_write(paddr, mask); -} - -/* Clear all output pins in the mask */ -void bcm2835_gpio_clr_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4; - bcm2835_peri_write(paddr, mask); -} - -/* Read input pin */ -uint8_t bcm2835_gpio_lev(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEV0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = bcm2835_peri_read(paddr); - return (value & (1 << shift)) ? HIGH : LOW; -} - -/* See if an event detection bit is set -// Sigh cant support interrupts yet -*/ -uint8_t bcm2835_gpio_eds(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = bcm2835_peri_read(paddr); - return (value & (1 << shift)) ? HIGH : LOW; -} - -uint32_t bcm2835_gpio_eds_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; - uint32_t value = bcm2835_peri_read(paddr); - return (value & mask); -} - -/* Write a 1 to clear the bit in EDS */ -void bcm2835_gpio_set_eds(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_write(paddr, value); -} - -void bcm2835_gpio_set_eds_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; - bcm2835_peri_write(paddr, mask); -} - -/* Rising edge detect enable */ -void bcm2835_gpio_ren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_ren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Falling edge detect enable */ -void bcm2835_gpio_fen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_fen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* High detect enable */ -void bcm2835_gpio_hen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_hen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Low detect enable */ -void bcm2835_gpio_len(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_len(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Async rising edge detect enable */ -void bcm2835_gpio_aren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_aren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Async falling edge detect enable */ -void bcm2835_gpio_afen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_afen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -/* Set pullup/down */ -void bcm2835_gpio_pud(uint8_t pud) -{ - if( pud_type_rpi4 ) { - pud_compat_setting = pud; - } else { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD/4; - bcm2835_peri_write(paddr, pud); - } -} - -/* Pullup/down clock -// Clocks the value of pud into the GPIO pin -*/ -void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on) -{ - if( pud_type_rpi4 ) { - if( on ) { - bcm2835_gpio_set_pud( pin, pud_compat_setting); - } - } else { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUDCLK0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); - } -} - -/* Read GPIO pad behaviour for groups of GPIOs */ -uint32_t bcm2835_gpio_pad(uint8_t group) -{ - if (bcm2835_pads == MAP_FAILED) { - return 0; - } - - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; - return bcm2835_peri_read(paddr); -} - -/* Set GPIO pad behaviour for groups of GPIOs -// powerup value for all pads is -// BCM2835_PAD_SLEW_RATE_UNLIMITED | BCM2835_PAD_HYSTERESIS_ENABLED | BCM2835_PAD_DRIVE_8mA -*/ -void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) -{ - if (bcm2835_pads == MAP_FAILED) { - return; - } - - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; - bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD); -} - -/* Some convenient arduino-like functions -// milliseconds -*/ -void bcm2835_delay(unsigned int millis) -{ - struct timespec sleeper; - - sleeper.tv_sec = (time_t)(millis / 1000); - sleeper.tv_nsec = (long)(millis % 1000) * 1000000; - nanosleep(&sleeper, NULL); -} - -/* microseconds */ -void bcm2835_delayMicroseconds(uint64_t micros) -{ - struct timespec t1; - uint64_t start; - - if (debug) { - /* Cant access sytem timers in debug mode */ - printf("bcm2835_delayMicroseconds %lld\n", (long long int) micros); - return; - } - - /* Calling nanosleep() takes at least 100-200 us, so use it for - // long waits and use a busy wait on the System Timer for the rest. - */ - start = bcm2835_st_read(); - - /* Not allowed to access timer registers (result is not as precise)*/ - if (start==0) { - t1.tv_sec = 0; - t1.tv_nsec = 1000 * (long)(micros); - nanosleep(&t1, NULL); - return; - } - - if (micros > 450) { - t1.tv_sec = 0; - t1.tv_nsec = 1000 * (long)(micros - 200); - nanosleep(&t1, NULL); - } - - bcm2835_st_delay(start, micros); -} - -/* -// Higher level convenience functions -*/ - -/* Set the state of an output */ -void bcm2835_gpio_write(uint8_t pin, uint8_t on) -{ - if (on) { - bcm2835_gpio_set(pin); - } else { - bcm2835_gpio_clr(pin); - } -} - -/* Set the state of a all 32 outputs in the mask to on or off */ -void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on) -{ - if (on) { - bcm2835_gpio_set_multi(mask); - } else { - bcm2835_gpio_clr_multi(mask); - } -} - -/* Set the state of a all 32 outputs in the mask to the values in value */ -void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) -{ - bcm2835_gpio_set_multi(value & mask); - bcm2835_gpio_clr_multi((~value) & mask); -} - -/* Set the pullup/down resistor for a pin -// -// The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on -// the respective GPIO pins. These registers must be used in conjunction with the GPPUD -// register to effect GPIO Pull-up/down changes. The following sequence of events is -// required: -// 1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither -// to remove the current Pull-up/down) -// 2. Wait 150 cycles ? this provides the required set-up time for the control signal -// 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to -// modify ? NOTE only the pads which receive a clock will be modified, all others will -// retain their previous state. -// 4. Wait 150 cycles ? this provides the required hold time for the control signal -// 5. Write to GPPUD to remove the control signal -// 6. Write to GPPUDCLK0/1 to remove the clock -// -// RPi has P1-03 and P1-05 with 1k8 pullup resistor -// -// RPI 4 uses a different PUD method - no clock - -*/ -void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud) -{ - if( pud_type_rpi4 ) { - int shiftbits = (pin & 0xf) << 1; - uint32_t bits; - uint32_t pull; - - switch (pud) { - case BCM2835_GPIO_PUD_OFF: - pull = 0; - break; - case BCM2835_GPIO_PUD_UP: - pull = 1; - break; - case BCM2835_GPIO_PUD_DOWN: - pull = 2; - break; - default: - return; - } - - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUPPDN0/4 + (pin >> 4); - - bits = bcm2835_peri_read_nb( paddr ); - bits &= ~(3 << shiftbits); - bits |= (pull << shiftbits); - - bcm2835_peri_write_nb( paddr, bits ); - - } else { - bcm2835_gpio_pud(pud); - delayMicroseconds(10); - bcm2835_gpio_pudclk(pin, 1); - delayMicroseconds(10); - bcm2835_gpio_pud(BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_pudclk(pin, 0); - } - -} - - -uint8_t bcm2835_gpio_get_pud(uint8_t pin) -{ - uint8_t ret = BCM2835_GPIO_PUD_ERROR; - - if( pud_type_rpi4 ) { - uint32_t bits; - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUPPDN0/4 + (pin >> 4); - bits = (bcm2835_peri_read_nb( paddr ) >> ((pin & 0xf)<<1)) & 0x3; - - switch (bits) { - case 0: - ret = BCM2835_GPIO_PUD_OFF; - break; - case 1: - ret = BCM2835_GPIO_PUD_UP; - break; - case 2: - ret = BCM2835_GPIO_PUD_DOWN; - break; - default: - ret = BCM2835_GPIO_PUD_ERROR; - } - } - - return ret; -} - - -int bcm2835_spi_begin(void) -{ - volatile uint32_t* paddr; - - if (bcm2835_spi0 == MAP_FAILED) { - return 0; /* bcm2835_init() failed, or not root */ - } - - /* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */ - bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); /* CE0 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); /* MISO */ - bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); /* MOSI */ - bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); /* CLK */ - - /* Set the SPI CS register to the some sensible defaults */ - paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - bcm2835_peri_write(paddr, 0); /* All 0s */ - - /* Clear TX and RX fifos */ - bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); - - return 1; // OK -} - -void bcm2835_spi_end(void) -{ - /* Set all the SPI0 pins back to input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); /* CE1 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); /* CE0 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); /* MISO */ - bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); /* MOSI */ - bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); /* CLK */ -} - -void bcm2835_spi_setBitOrder(uint8_t order) -{ - bcm2835_spi_bit_order = order; -} - -/* defaults to 0, which means a divider of 65536. -// The divisor must be a power of 2. Odd numbers -// rounded down. The maximum SPI clock rate is -// of the APB clock -*/ -void bcm2835_spi_setClockDivider(uint16_t divider) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK/4; - bcm2835_peri_write(paddr, divider); -} - -void bcm2835_spi_set_speed_hz(uint32_t speed_hz) -{ - uint16_t divider = (uint16_t) ((uint32_t) BCM2835_CORE_CLK_HZ / speed_hz); - divider &= 0xFFFE; - bcm2835_spi_setClockDivider(divider); -} - -void bcm2835_spi_setDataMode(uint8_t mode) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - /* Mask in the CPO and CPHA bits of CS */ - bcm2835_peri_set_bits(paddr, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA); -} - -/* Writes (and reads) a single byte to SPI */ -uint8_t bcm2835_spi_transfer(uint8_t value) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t ret; - - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - // Clear TX and RX fifos - */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - /* Write to FIFO, no barrier */ - bcm2835_peri_write_nb(fifo, bcm2835_correct_order(value)); - - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; - - /* Read any byte that was sent back by the slave while we sere sending to it */ - ret = bcm2835_correct_order(bcm2835_peri_read_nb(fifo)); - - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); - - return ret; -} - -/* Writes (and reads) an number of bytes to SPI */ -void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t TXCnt=0; - uint32_t RXCnt=0; - - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - */ - - /* Clear TX and RX fifos */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - /* Use the FIFO's to reduce the interbyte times */ - while((TXCnt < len)||(RXCnt < len)) { - /* TX fifo not full, so add some more bytes */ - while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) { - bcm2835_peri_write_nb(fifo, bcm2835_correct_order(tbuf[TXCnt])); - TXCnt++; - } - /* Rx fifo not empty, so get the next received bytes */ - while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) { - rbuf[RXCnt] = bcm2835_correct_order(bcm2835_peri_read_nb(fifo)); - RXCnt++; - } - } - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; - - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -} - -/* Writes an number of bytes to SPI */ -void bcm2835_spi_writenb(const char* tbuf, uint32_t len) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t i; - - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - // Answer: an ISR is required to issue the required memory barriers. - */ - - /* Clear TX and RX fifos */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - for (i = 0; i < len; i++) { - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - /* Write to FIFO, no barrier */ - bcm2835_peri_write_nb(fifo, bcm2835_correct_order(tbuf[i])); - - /* Read from FIFO to prevent stalling */ - while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) { - (void) bcm2835_peri_read_nb(fifo); - } - } - - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) { - while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) { - (void) bcm2835_peri_read_nb(fifo); - } - }; - - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -} - -/* Writes (and reads) an number of bytes to SPI -// Read bytes are copied over onto the transmit buffer -*/ -void bcm2835_spi_transfern(char* buf, uint32_t len) -{ - bcm2835_spi_transfernb(buf, buf, len); -} - -void bcm2835_spi_chipSelect(uint8_t cs) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - /* Mask in the CS bits of CS */ - bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); -} - -void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - uint8_t shift = 21 + cs; - /* Mask in the appropriate CSPOLn bit */ - bcm2835_peri_set_bits(paddr, active << shift, 1 << shift); -} - -void bcm2835_spi_write(uint16_t data) -{ -#if 0 - char buf[2]; - - buf[0] = data >> 8; - buf[1] = data & 0xFF; - - bcm2835_spi_transfern(buf, 2); -#else - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - - /* Clear TX and RX fifos */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - /* Write to FIFO */ - bcm2835_peri_write_nb(fifo, (uint32_t) data >> 8); - bcm2835_peri_write_nb(fifo, data & 0xFF); - - - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; - - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -#endif -} - -int bcm2835_aux_spi_begin(void) -{ - volatile uint32_t* enable = bcm2835_aux + BCM2835_AUX_ENABLE/4; - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - - if (bcm2835_spi1 == MAP_FAILED) { - return 0; /* bcm2835_init() failed, or not root */ - } - - /* Set the SPI pins to the Alt 4 function to enable SPI1 access on them */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_ALT4); /* SPI1_CE2_N */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MISO */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MOSI */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_ALT4); /* SPI1_SCLK */ - - bcm2835_aux_spi_setClockDivider(bcm2835_aux_spi_CalcClockDivider(1000000)); // Default 1MHz SPI - - bcm2835_peri_write(enable, BCM2835_AUX_ENABLE_SPI0); - bcm2835_peri_write(cntl1, 0); - bcm2835_peri_write(cntl0, BCM2835_AUX_SPI_CNTL0_CLEARFIFO); - - return 1; /* OK */ -} - -void bcm2835_aux_spi_end(void) -{ - /* Set all the SPI1 pins back to input */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_INPT); /* SPI1_CE2_N */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_INPT); /* SPI1_MISO */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_INPT); /* SPI1_MOSI */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_INPT); /* SPI1_SCLK */ -} - -#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) - -uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz) -{ - uint16_t divider; - - if (speed_hz < (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN) { - speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN; - } else if (speed_hz > (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX) { - speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX; - } - - divider = (uint16_t) DIV_ROUND_UP(BCM2835_CORE_CLK_HZ, 2 * speed_hz) - 1; - - if (divider > (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX) { - return (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX; - } - - return divider; -} - -static uint32_t spi1_speed; - -void bcm2835_aux_spi_setClockDivider(uint16_t divider) -{ - spi1_speed = (uint32_t) divider; -} - -void bcm2835_aux_spi_write(uint16_t data) -{ - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; - - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= 16; // Shift length - - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) - ; - - bcm2835_peri_write(io, (uint32_t) data << 16); -} - -void bcm2835_aux_spi_writenb(const char *tbuf, uint32_t len) -{ - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; - - char *tx = (char *) tbuf; - uint32_t tx_len = len; - uint32_t count; - uint32_t data; - uint32_t i; - uint8_t byte; - - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH; - - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - - while (tx_len > 0) { - - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) - ; - - count = MIN(tx_len, 3); - data = 0; - - for (i = 0; i < count; i++) { - byte = (tx != NULL) ? (uint8_t) *tx++ : (uint8_t) 0; - data |= byte << (8 * (2 - i)); - } - - data |= (count * 8) << 24; - tx_len -= count; - - if (tx_len != 0) { - bcm2835_peri_write(txhold, data); - } else { - bcm2835_peri_write(io, data); - } - - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY) - ; - - (void) bcm2835_peri_read(io); - } -} - -void bcm2835_aux_spi_transfernb(const char *tbuf, char *rbuf, uint32_t len) -{ - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; - - char *tx = (char *)tbuf; - char *rx = (char *)rbuf; - uint32_t tx_len = len; - uint32_t rx_len = len; - uint32_t count; - uint32_t data; - uint32_t i; - uint8_t byte; - - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH; - - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - - while ((tx_len > 0) || (rx_len > 0)) { - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) && (tx_len > 0)) { - count = MIN(tx_len, 3); - data = 0; - - for (i = 0; i < count; i++) { - byte = (tx != NULL) ? (uint8_t) *tx++ : (uint8_t) 0; - data |= byte << (8 * (2 - i)); - } - - data |= (count * 8) << 24; - tx_len -= count; - - if (tx_len != 0) { - bcm2835_peri_write(txhold, data); - } else { - bcm2835_peri_write(io, data); - } - - } - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_RX_EMPTY) && (rx_len > 0)) { - count = MIN(rx_len, 3); - data = bcm2835_peri_read(io); - - if (rbuf != NULL) { - switch (count) { - case 3: - *rx++ = (char)((data >> 16) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 2: - *rx++ = (char)((data >> 8) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 1: - *rx++ = (char)((data >> 0) & 0xFF); - } - } - - rx_len -= count; - } - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY) && (rx_len > 0)) { - count = MIN(rx_len, 3); - data = bcm2835_peri_read(io); - - if (rbuf != NULL) { - switch (count) { - case 3: - *rx++ = (char)((data >> 16) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 2: - *rx++ = (char)((data >> 8) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 1: - *rx++ = (char)((data >> 0) & 0xFF); - } - } - - rx_len -= count; - } - } -} - -void bcm2835_aux_spi_transfern(char *buf, uint32_t len) -{ - bcm2835_aux_spi_transfernb(buf, buf, len); -} - -int bcm2835_i2c_begin(void) -{ - uint16_t cdiv; - - if ( bcm2835_bsc0 == MAP_FAILED - || bcm2835_bsc1 == MAP_FAILED) { - return 0; /* bcm2835_init() failed, or not root */ - } - -#ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; - /* Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them */ - bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ - bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; - /* Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ -#endif - - /* Read the clock divider register */ - cdiv = bcm2835_peri_read(paddr); - /* Calculate time for transmitting one byte - // 1000000 = micros seconds in a second - // 9 = Clocks per byte : 8 bits + ACK - */ - i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9; - - return 1; -} - -void bcm2835_i2c_end(void) -{ -#ifdef I2C_V1 - /* Set all the I2C/BSC0 pins back to input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ - bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ -#else - /* Set all the I2C/BSC1 pins back to input */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ -#endif -} - -void bcm2835_i2c_setSlaveAddress(uint8_t addr) -{ - /* Set I2C Device Address */ -#ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; -#endif - bcm2835_peri_write(paddr, addr); -} - -/* defaults to 0x5dc, should result in a 166.666 kHz I2C clock frequency. -// The divisor must be a power of 2. Odd numbers -// rounded down. -*/ -void bcm2835_i2c_setClockDivider(uint16_t divider) -{ -#ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; -#endif - bcm2835_peri_write(paddr, divider); - /* Calculate time for transmitting one byte - // 1000000 = micros seconds in a second - // 9 = Clocks per byte : 8 bits + ACK - */ - i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; -} - -/* set I2C clock divider by means of a baudrate number */ -void bcm2835_i2c_set_baudrate(uint32_t baudrate) -{ - uint32_t divider; - /* use 0xFFFE mask to limit a max value and round down any odd number */ - divider = (BCM2835_CORE_CLK_HZ / baudrate) & 0xFFFE; - bcm2835_i2c_setClockDivider( (uint16_t)divider ); -} - -/* Writes an number of bytes to I2C */ -uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) -{ -#ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1, BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write(dlen, len); - /* pre populate FIFO with max buffer */ - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) { - bcm2835_peri_write_nb(fifo, buf[i]); - i++; - remaining--; - } - - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* Transfer is over when BCM2835_BSC_S_DONE */ - while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) { - while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) { - /* Write to FIFO */ - bcm2835_peri_write(fifo, buf[i]); - i++; - remaining--; - } - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - /* Not all data is sent */ - else if (remaining) { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE, BCM2835_BSC_S_DONE); - - return reason; -} - -/* Read an number of bytes from I2C */ -uint8_t bcm2835_i2c_read(char* buf, uint32_t len) -{ -#ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1, BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write_nb(dlen, len); - /* Start read */ - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) { - /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - /* Not all data is received */ - else if (remaining) { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE, BCM2835_BSC_S_DONE); - - return reason; -} - -/* Read an number of bytes from I2C sending a repeated start after writing -// the required register. Only works if your device supports this mode -*/ -uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len) -{ -#ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1, BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write(dlen, 1); - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN); - bcm2835_peri_write(fifo, regaddr[0]); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* poll for transfer has started */ - while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) { - /* Linux may cause us to miss entire transfer stage */ - if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) { - break; - } - } - - /* Send a repeated start with read bit set in address */ - bcm2835_peri_write(dlen, len); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - - /* Wait for write to complete and first byte back. */ - bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) { - /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - /* Not all data is sent */ - else if (remaining) { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE, BCM2835_BSC_S_DONE); - - return reason; -} - -/* Sending an arbitrary number of bytes before issuing a repeated start -// (with no prior stop) and reading a response. Some devices require this behavior. -*/ -uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len) -{ -#ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - - uint32_t remaining = cmds_len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1, BCM2835_BSC_C_CLEAR_1 ); - - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - - /* Set Data Length */ - bcm2835_peri_write(dlen, cmds_len); - - /* pre populate FIFO with max buffer */ - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) { - bcm2835_peri_write_nb(fifo, cmds[i]); - i++; - remaining--; - } - - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ - while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) { - /* Linux may cause us to miss entire transfer stage */ - if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) { - break; - } - } - - remaining = buf_len; - i = 0; - - /* Send a repeated start with read bit set in address */ - bcm2835_peri_write(dlen, buf_len); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - - /* Wait for write to complete and first byte back. */ - bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1)); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) { - /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - /* Not all data is sent */ - else if (remaining) { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE, BCM2835_BSC_S_DONE); - - return reason; -} - -/* Read the System Timer Counter (64-bits) */ -uint64_t bcm2835_st_read(void) -{ - volatile uint32_t* paddr; - uint32_t hi, lo; - uint64_t st; - - if (bcm2835_st==MAP_FAILED) { - return 0; - } - - paddr = bcm2835_st + BCM2835_ST_CHI/4; - hi = bcm2835_peri_read(paddr); - - paddr = bcm2835_st + BCM2835_ST_CLO/4; - lo = bcm2835_peri_read(paddr); - - paddr = bcm2835_st + BCM2835_ST_CHI/4; - st = bcm2835_peri_read(paddr); - - /* Test for overflow */ - if (st == hi) { - st <<= 32; - st += lo; - } else { - st <<= 32; - paddr = bcm2835_st + BCM2835_ST_CLO/4; - st += bcm2835_peri_read(paddr); - } - return st; -} - -/* Delays for the specified number of microseconds with offset */ -void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros) -{ - uint64_t compare = offset_micros + micros; - - while(bcm2835_st_read() < compare) - ; -} - -/* PWM */ - -void bcm2835_pwm_set_clock(uint32_t divisor) -{ - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) { - return; /* bcm2835_init() failed or not root */ - } - - /* From Gerts code */ - divisor &= 0xfff; - /* Stop PWM clock */ - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); - bcm2835_delay(110); /* Prevents clock going slow */ - /* Wait for the clock to be not busy */ - while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) { - bcm2835_delay(1); - } - /* set the clock divider and enable PWM clock */ - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12)); - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, - BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */ -} - -void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled) -{ - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) { - return; /* bcm2835_init() failed or not root */ - } - - uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL); - - if (channel == 0) { - if (markspace) { - control |= BCM2835_PWM0_MS_MODE; - } else { - control &= ~BCM2835_PWM0_MS_MODE; - } - if (enabled) { - control |= BCM2835_PWM0_ENABLE; - } else { - control &= ~BCM2835_PWM0_ENABLE; - } - } else if (channel == 1) { - if (markspace) { - control |= BCM2835_PWM1_MS_MODE; - } else { - control &= ~BCM2835_PWM1_MS_MODE; - } - if (enabled) { - control |= BCM2835_PWM1_ENABLE; - } else { - control &= ~BCM2835_PWM1_ENABLE; - } - } - - /* If you use the barrier here, wierd things happen, and the commands dont work */ - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control); - /* bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); */ - -} - -void bcm2835_pwm_set_range(uint8_t channel, uint32_t range) -{ - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) { - return; /* bcm2835_init() failed or not root */ - } - - if (channel == 0) { - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range); - } else if (channel == 1) { - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range); - } -} - -void bcm2835_pwm_set_data(uint8_t channel, uint32_t data) -{ - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) { - return; /* bcm2835_init() failed or not root */ - } - - if (channel == 0) { - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data); - } else if (channel == 1) { - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data); - } -} - -/* Allocate page-aligned memory. */ -void *malloc_aligned(size_t size) -{ - void *mem; - errno = posix_memalign(&mem, BCM2835_PAGE_SIZE, size); - return (errno ? NULL : mem); -} - -/* Map 'size' bytes starting at 'off' in file 'fd' to memory. -// Return mapped address on success, MAP_FAILED otherwise. -// On error print message. -*/ -static void *mapmem(const char *msg, size_t size, int fd, off_t off) -{ - void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); - if (map == MAP_FAILED) { - fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); - } - return map; -} - -static void unmapmem(void **pmem, size_t size) -{ - if (*pmem == MAP_FAILED) { - return; - } - munmap(*pmem, size); - *pmem = MAP_FAILED; -} - -/* Initialise this library. */ -int bcm2835_init(void) -{ - int memfd; - int ok; - FILE *fp; - - if (debug) { - bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE; - - bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; - bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; - bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; - bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; - bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; - bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; - bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; - bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; - bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE/4; - bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE/4; - - return 1; /* Success */ - } - - /* Figure out the base and size of the peripheral address block - // using the device-tree. Required for RPi2/3/4, optional for RPi 1 - */ - if ((fp = fopen(BMC2835_RPI2_DT_FILENAME, "rb"))) { - unsigned char buf[16]; - uint32_t base_address; - uint32_t peri_size; - if (fread(buf, 1, sizeof(buf), fp) >= 8) { - base_address = (buf[4] << 24) | - (buf[5] << 16) | - (buf[6] << 8) | - (buf[7] << 0); - - peri_size = (buf[8] << 24) | - (buf[9] << 16) | - (buf[10] << 8) | - (buf[11] << 0); - - if (!base_address) { - /* looks like RPI 4 */ - base_address = (buf[8] << 24) | - (buf[9] << 16) | - (buf[10] << 8) | - (buf[11] << 0); - - peri_size = (buf[12] << 24) | - (buf[13] << 16) | - (buf[14] << 8) | - (buf[15] << 0); - } - /* check for valid known range formats */ - if ((buf[0] == 0x7e) && - (buf[1] == 0x00) && - (buf[2] == 0x00) && - (buf[3] == 0x00) && - ((base_address == BCM2835_PERI_BASE) || (base_address == BCM2835_RPI2_PERI_BASE) || - (base_address == BCM2835_RPI4_PERI_BASE))) { - bcm2835_peripherals_base = (uint32_t *)base_address; - bcm2835_peripherals_size = peri_size; - if( base_address == BCM2835_RPI4_PERI_BASE ) { - pud_type_rpi4 = 1; - } - } - - } - - fclose(fp); - } - /* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */ - - /* Now get ready to map the peripherals block - * If we are not root, try for the new /dev/gpiomem interface and accept - * the fact that we can only access GPIO - * else try for the /dev/mem interface and get access to everything - */ - memfd = -1; - ok = 0; - if (geteuid() == 0) { - /* Open the master /dev/mem device */ - if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) { - fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n", - strerror(errno)) ; - goto exit; - } - - /* Base of the peripherals block is mapped to VM */ - bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, - (off_t)bcm2835_peripherals_base); - if (bcm2835_peripherals == MAP_FAILED) { - goto exit; - } - - /* Now compute the base addresses of various peripherals, - // which are at fixed offsets within the mapped peripherals block - // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4 - */ - bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; - bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; - bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; - bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; - bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; - bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; /* I2C */ - bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */ - bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; - bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE/4; - bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE/4; - - ok = 1; - } else { - /* Not root, try /dev/gpiomem */ - /* Open the master /dev/mem device */ - if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) { - fprintf(stderr, "bcm2835_init: Unable to open /dev/gpiomem: %s\n", - strerror(errno)) ; - goto exit; - } - - /* Base of the peripherals block is mapped to VM */ - bcm2835_peripherals_base = 0; - bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, - (off_t)bcm2835_peripherals_base); - if (bcm2835_peripherals == MAP_FAILED) { - goto exit; - } - bcm2835_gpio = bcm2835_peripherals; - ok = 1; - } - -exit: - if (memfd >= 0) { - close(memfd); - } - - if (!ok) { - bcm2835_close(); - } - - return ok; -} - -/* Close this library and deallocate everything */ -int bcm2835_close(void) -{ - if (debug) { - return 1; /* Success */ - } - - unmapmem((void**) &bcm2835_peripherals, bcm2835_peripherals_size); - bcm2835_peripherals = MAP_FAILED; - bcm2835_gpio = MAP_FAILED; - bcm2835_pwm = MAP_FAILED; - bcm2835_clk = MAP_FAILED; - bcm2835_pads = MAP_FAILED; - bcm2835_spi0 = MAP_FAILED; - bcm2835_bsc0 = MAP_FAILED; - bcm2835_bsc1 = MAP_FAILED; - bcm2835_st = MAP_FAILED; - bcm2835_aux = MAP_FAILED; - bcm2835_spi1 = MAP_FAILED; - return 1; /* Success */ -} - -#ifdef BCM2835_TEST -/* this is a simple test program that prints out what it will do rather than -// actually doing it -*/ -int main(int argc, char **argv) -{ - /* Be non-destructive */ - bcm2835_set_debug(1); - - if (!bcm2835_init()) { - return 1; - } - - /* Configure some GPIO pins fo some testing - // Set RPI pin P1-11 to be an output - */ - bcm2835_gpio_fsel(RPI_GPIO_P1_11, BCM2835_GPIO_FSEL_OUTP); - /* Set RPI pin P1-15 to be an input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_15, BCM2835_GPIO_FSEL_INPT); - /* with a pullup */ - bcm2835_gpio_set_pud(RPI_GPIO_P1_15, BCM2835_GPIO_PUD_UP); - /* And a low detect enable */ - bcm2835_gpio_len(RPI_GPIO_P1_15); - /* and input hysteresis disabled on GPIOs 0 to 27 */ - bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, - BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA); - -#if 1 - /* Blink */ - while (1) { - /* Turn it on */ - bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); - - /* wait a bit */ - bcm2835_delay(500); - - /* turn it off */ - bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); - - /* wait a bit */ - bcm2835_delay(500); - } -#endif - -#if 0 - /* Read input */ - while (1) { - /* Read some data */ - uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); - printf("read from pin 15: %d\n", value); - - /* wait a bit */ - bcm2835_delay(500); - } -#endif - -#if 0 - /* Look for a low event detection - // eds will be set whenever pin 15 goes low - */ - while (1) { - if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) { - /* Now clear the eds flag by setting it to 1 */ - bcm2835_gpio_set_eds(RPI_GPIO_P1_15); - printf("low event detect for pin 15\n"); - } - - /* wait a bit */ - bcm2835_delay(500); - } -#endif - - if (!bcm2835_close()) { - return 1; - } - - return 0; -} -#endif - - - diff --git a/lib/MySensors/hal/architecture/Linux/drivers/BCM/bcm2835.h b/lib/MySensors/hal/architecture/Linux/drivers/BCM/bcm2835.h deleted file mode 100644 index 3a8f78ce..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/BCM/bcm2835.h +++ /dev/null @@ -1,1951 +0,0 @@ -/* bcm2835.h - - C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi - - Author: Mike McCauley - Copyright (C) 2011-2013 Mike McCauley - $Id: bcm2835.h,v 1.25 2019/07/22 23:04:13 mikem Exp $ -*/ - -/*! \defgroup BCM2835grp C library for Broadcom BCM 2835 as used in Raspberry Pi - - This is a C library for Raspberry Pi (RPi). It provides access to - GPIO and other IO functions on the Broadcom BCM 2835 chip, as used in the RaspberryPi, - allowing access to the GPIO pins on the - 26 pin IDE plug on the RPi board so you can control and interface with various external devices. - - It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, - and for accessing the system timers. - Pin event detection is supported by polling (interrupts are not supported). - - Works on all versions upt to and including RPI 4. - Works with all versions of Debian up to and including Debian Buster 10. - - It is C++ compatible, and installs as a header file and non-shared library on - any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with - BCM 2835). - - The version of the package that this documentation refers to can be downloaded - from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.60.tar.gz - You can find the latest version at http://www.airspayce.com/mikem/bcm2835 - - Several example programs are provided. - - Based on data in http://elinux.org/RPi_Low-level_peripherals and - http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf - and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 - - You can also find online help and discussion at http://groups.google.com/group/bcm2835 - Please use that group for all questions and discussions on this topic. - Do not contact the author directly, unless it is to discuss commercial licensing. - Before asking a question or reporting a bug, please read - - http://en.wikipedia.org/wiki/Wikipedia:Reference_desk/How_to_ask_a_software_question - - http://www.catb.org/esr/faqs/smart-questions.html - - http://www.chiark.greenend.org.uk/~shgtatham/bugs.html - - Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian - and Occidentalisv01, 2016-02-09 Raspbian Jessie. - CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() - are used and the pin is pulled LOW - it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian - and Occidentalisv01. - Reason for this is not yet determined, but we suspect that an interrupt handler is - hitting a hard loop on those OSs. - If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with - bcm2835_gpio_clr_len() and friends after use. - - \par Running as root - - Prior to the release of Raspbian Jessie in Feb 2016, access to any - peripheral device via /dev/mem on the RPi required the process to - run as root. Raspbian Jessie permits non-root users to access the - GPIO peripheral (only) via /dev/gpiomem, and this library supports - that limited mode of operation. - - If the library runs with effective UID of 0 (ie root), then - bcm2835_init() will attempt to open /dev/mem, and, if successful, it - will permit use of all peripherals and library functions. - - If the library runs with any other effective UID (ie not root), then - bcm2835_init() will attempt to open /dev/gpiomem, and, if - successful, will only permit GPIO operations. In particular, - bcm2835_spi_begin() and bcm2835_i2c_begin() will return false and all - other non-gpio operations may fail silently or crash. - - \par Installation - - This library consists of a single non-shared library and header file, which will be - installed in the usual places by make install - - \code - # download the latest version of the library, say bcm2835-1.xx.tar.gz, then: - tar zxvf bcm2835-1.xx.tar.gz - cd bcm2835-1.xx - ./configure - make - sudo make check - sudo make install - \endcode - - \par Physical Addresses - - The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() - are low level peripheral register access functions. They are designed to use - physical addresses as described in section 1.2.3 ARM physical addresses - of the BCM2835 ARM Peripherals manual. - Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus - addresses for peripherals are set up to map onto the peripheral bus address range starting at - 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at - physical address 0x20nnnnnn. - - On RPI 2, the peripheral addresses are different and the bcm2835 library gets them - from reading /proc/device-tree/soc/ranges. This is only availble with recent versions of the kernel on RPI 2. - - After initialisation, the base address of the various peripheral - registers are available with the following - externals: - bcm2835_gpio - bcm2835_pwm - bcm2835_clk - bcm2835_pads - bcm2835_spio0 - bcm2835_st - bcm2835_bsc0 - bcm2835_bsc1 - bcm2835_aux - bcm2835_spi1 - - \par Raspberry Pi 2 (RPI2) - - For this library to work correctly on RPI2, you MUST have the device tree support enabled in the kernel. - You should also ensure you are using the latest version of Linux. The library has been tested on RPI2 - with 2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29. - - When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system, - and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1). - Without device tree support enabled and the presence of this file, it will not work on RPI2. - - To enable device tree support: - - \code - sudo raspi-config - under Advanced Options - enable Device Tree - Reboot. - \endcode - - \par Pin Numbering - - The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying - BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs - - RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, - as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the - IDE header. - - RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd. - - The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ - the RPi pin number. There are symbolic definitions for each of the available pins - that you should use for convenience. See \ref RPiGPIOPin. - - \par SPI Pins - - The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, - allowing you to send and received data by SPI (Serial Peripheral Interface). - For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus - - When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their - default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able - to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). - When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be - configured and controled with the usual bcm2835_gpio_* calls. - - The Raspberry Pi GPIO pins used for SPI are: - - - P1-19 (MOSI) - - P1-21 (MISO) - - P1-23 (CLK) - - P1-24 (CE0) - - P1-26 (CE1) - - Although it is possible to select high speeds for the SPI interface, up to 125MHz (see bcm2835_spi_setClockDivider()) - you should not expect to actually achieve those sorts of speeds with the RPi wiring. Our tests on RPi 2 show that the - SPI CLK line when unloaded has a resonant frequency of about 40MHz, and when loaded, the MOSI and MISO lines - ring at an even lower frequency. Measurements show that SPI waveforms are very poor and unusable at 62 and 125MHz. - Dont expect any speed faster than 31MHz to work reliably. - - The bcm2835_aux_spi_* functions allow you to control the BCM 2835 SPI1 interface, - allowing you to send and received data by SPI (Serial Peripheral Interface). - - The Raspberry Pi GPIO pins used for AUX SPI (SPI1) are: - - - P1-38 (MOSI) - - P1-35 (MISO) - - P1-40 (CLK) - - P1-36 (CE2) - - \par I2C Pins - - The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, - allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . - For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C - - The Raspberry Pi V2 GPIO pins used for I2C are: - - - P1-03 (SDA) - - P1-05 (SLC) - - \par PWM - - The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides - functions for configuring and controlling PWM output on these pins. - - The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of - GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5): - \code - GPIO PIN RPi pin PWM Channel ALT FUN - 12 0 0 - 13 1 0 - 18 1-12 0 5 - 19 1 5 - 40 0 0 - 41 1 0 - 45 1 0 - 52 0 1 - 53 1 1 - \endcode - In order for a GPIO pin to emit output from its PWM channel, it must be set to the Alt Function given above. - Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12) - on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM. - Further it must be set to ALT FUN 5 to get PWM output. - - Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using - bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode(). - The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel. - Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio - - Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware - sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses. - In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by - LOW for RANGE-DATA clock pulses. - - The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from - a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_* - values of \ref bcm2835PWMClockDivider. - - For example, say you wanted to drive a DC motor with PWM at about 1kHz, - and control the speed in 1/1024 increments from - 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the - clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be - 1.2MHz/1024 = 1171.875Hz. - - \par Interactions with other systems - - In order for bcm2835 library SPI to work, you may need to disable the SPI kernel module using: - - \code - sudo raspi-config - under Advanced Options - enable Device Tree - under Advanced Options - disable SPI - Reboot. - \endcode - - Since bcm2835 accesses the lowest level hardware interfaces (in eh intererests of speed and flexibility) - there can be intercations with other low level software trying to do similar things. - - It seems that with "latest" 8.0 Jessie 4.9.24-v7+ kernel PWM just won't - work unless you disable audio. There's a line - \code - dtparam=audio=on - \endcode - in the /boot/config.txt. - Comment it out like this: - \code - #dtparam=audio=on - \endcode - - \par Real Time performance constraints - - The bcm2835 is a library for user programs (i.e. they run in 'userland'). - Such programs are not part of the kernel and are usually - subject to paging and swapping by the kernel while it does other things besides running your program. - This means that you should not expect to get real-time performance or - real-time timing constraints from such programs. In particular, there is no guarantee that the - bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. - In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times - than the one you asked for. So please dont expect to get exactly the time delay you request. - - Arjan reports that you can prevent swapping on Linux with the following code fragment: - - \code - #define - #define - - struct sched_param sp; - memset(&sp, 0, sizeof(sp)); - sp.sched_priority = sched_get_priority_max(SCHED_FIFO); - sched_setscheduler(0, SCHED_FIFO, &sp); - mlockall(MCL_CURRENT | MCL_FUTURE); - \endcode - - \par Crashing on some versions of Raspbian - Some people have reported that various versions of Rasbian will crash or hang - if certain GPIO pins are toggled: https://github.com/raspberrypi/linux/issues/2550 - when using bcm2835. - A workaround is to add this line to your /boot/config.txt: - \code - dtoverlay=gpio-no-irq - \endcode - - \par Bindings to other languages - - mikem has made Perl bindings available at CPAN: - http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm - Matthew Baker has kindly made Python bindings available at: - https: github.com/mubeta06/py-libbcm2835 - Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility - for Raspberry Pi, based on the bcm2835 library. The - utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a - free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ - - \par Open Source Licensing GPL V2 - - This is the appropriate option if you want to share the source code of your - application with everyone you distribute it to, and you also want to give them - the right to share who uses it. If you wish to use this software under Open - Source Licensing, you must contribute all your source code to the open source - community in accordance with the GPL Version 2 when your application is - distributed. See https://www.gnu.org/licenses/gpl-2.0.html and COPYING - - \par Commercial Licensing - - This is the appropriate option if you are creating proprietary applications - and you are not prepared to distribute and share the source code of your - application. To purchase a commercial license, contact info@airspayce.com - - \par Acknowledgements - - Some of this code has been inspired by Dom and Gert. - The I2C code has been inspired by Alan Barr. - - \par Revision History - - \version 1.0 Initial release - - \version 1.1 Minor bug fixes - - \version 1.2 Added support for SPI - - \version 1.3 Added bcm2835_spi_transfern() - - \version 1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson. - - \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz - - \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 - Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen() - bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now - changes only the pin specified. Other pins that were already previously - enabled stay enabled. - Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen() - bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() - to clear the enable for individual pins, suggested by Andreas Sundstrom. - - \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write. - - \version 1.8 Improvements to read barrier, as suggested by maddin. - - \version 1.9 Improvements contributed by mikew: - I noticed that it was mallocing memory for the mmaps on /dev/mem. - It's not necessary to do that, you can just mmap the file directly, - so I've removed the mallocs (and frees). - I've also modified delayMicroseconds() to use nanosleep() for long waits, - and a busy wait on a high resolution timer for the rest. This is because - I've found that calling nanosleep() takes at least 100-200 us. - You need to link using '-lrt' using this version. - I've added some unsigned casts to the debug prints to silence compiler - warnings I was getting, fixed some typos, and changed the value of - BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at - http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 - Also added a define for the passwrd value that Gert says is needed to - change pad control settings. - - \version 1.10 Changed the names of the delay functions to bcm2835_delay() - and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. - Macros to map delay()-> bcm2835_delay() and - Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which - can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY - - \version 1.11 Fixed incorrect link to download file - - \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) - - \version 1.13 New GPIO pin definitions for RPi version 2 plug P5 - Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio - bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0. - - \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. - Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. - Reported by Ben Simpson. - - \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe. - - \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi - to allow a mask of pins to be set all at once. Requested by Sebastian Loncar. - - \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar. - - \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: - now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. - No need to link with -lrt now. Contributed by Arjan van Vught. - \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. - Reported by olly. - - \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted. - - \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. - Patch courtesy Jeremy Mortis. - - \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set - falling edge events. Reported by Mark Dootson. - - \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. - Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions - to fix ocasional reads not completing. Patched by Mark Dootson. - - \version 1.24 Mark Dootson p[atched a problem with his previously submitted code - under high load from other processes. - - \version 1.25 Updated author and distribution location details to airspayce.com - - \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. - Reported by Hartmut Henkel. - - \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is - now automatically included. - Added support for PWM mode with bcm2835_pwm_* functions. - - \version 1.28 Fixed a problem where bcm2835_spi_writenb() would have problems with transfers of more than - 64 bytes dues to read buffer filling. Patched by Peter Würtz. - - \version 1.29 Further fix to SPI from Peter Würtz. - - \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for - significant performance improvements, Patch by Alan Watson. - - \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks. - - \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi. - By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. - Contributed by Malcolm Wiles based on work by Arvi Govindaraj. - - \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia. - - \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, - sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst. - - \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed b Udo Klaas. - - \version 1.36 Make automake's test runner detect that we're skipping tests when not root, the second - one makes us skip the test when using fakeroot (as used when building - Debian packages). Contributed by Guido Günther. - - \version 1.37 Moved confiure.in to configure.ac as receommnded by autoreconf.
- Improvements to bcm2835_st_read to account for possible timer overflow, contributed by 'Ed'.
- Added definitions for Raspberry Pi B+ J8 header GPIO pins.
- - \version 1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers
- - \version 1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware. - Testers please confirm correct operation on RPi2.
- Unnecessary 'volatile' qualifiers removed from all variables and signatures.
- Removed unsupportable PWM dividers, based on a report from Christophe Cecillon.
- Minor improvements to spi.c example.
- - \version 1.40 Correct operation on RPi2 has been confirmed.
- Fixed a number of compiler errors and warnings that occur when bcm2835.h is included - in code compiled with -Wall -Woverflow -Wstrict-overflow -Wshadow -Wextra -pedantic. - Reported by tlhackque.
- Fixed a problem where calling bcm2835_delayMicroseconds loops forever when debug is set. Reported by tlhackque.
- Reinstated use of volatile in 2 functions where there was a danger of lost reads or writes. Reported by tlhackque.
- - \version 1.41 Added BCM2835_VERSION macro and new function bcm2835_version(); Requested by tlhackque.
- Improvements to peripheral memory barriers as suggested by tlhackque.
- Reinstated some necessary volatile declarations as requested by tlhackque.
- - \version 1.42 Further improvements to memory barriers with the patient assistance and patches of tlhackque.
- - \version 1.43 Fixed problems with compiling barriers on RPI 2 with Arch Linux and gcc 4.9.2. - Reported and patched by Lars Christensen.
- Testing on RPI 2, with ArchLinuxARM-rpi-2-latest and 2015-02-16-raspbian-wheezy.
- - \version 1.44 Added documention about the need for device tree to be enabled on RPI2.
- Improvements to detection of availability of DMB instruction based on value of __ARM_ARCH macro.
- - \version 1.45 Fixed an error in the pad group offsets that would prevent bcm2835_gpio_set_pad() - and bcm2835_gpio_pad() working correctly with non-0 pad groups. Reported by Guido. - - \version 1.46 2015-09-18 - Added symbolic definitions for remaining pins on 40 pin GPIO header on RPi 2.
- - \version 1.47 2015-11-18 - Fixed possibly incorrect reads in bcm2835_i2c_read_register_rs, patch from Eckhardt Ulrich.
- - \version 1.48 2015-12-08 - Added patch from Eckhardt Ulrich that fixed problems that could cause hanging with bcm2835_i2c_read_register_rs - and others. - - \version 1.49 2016-01-05 - Added patch from Jonathan Perkin with new functions bcm2835_gpio_eds_multi() and bcm2835_gpio_set_eds_multi(). - - \version 1.50 2016-02-28 - Added support for running as non-root, permitting access to GPIO only. Functions - bcm2835_spi_begin() and bcm2835_i2c_begin() will now return 0 if not running as root - (which prevents access to the SPI and I2C peripherals, amongst others). - Testing on Raspbian Jessie. - - \version 1.51 2016-11-03 - Added documentation about SPI clock divider and resulting SPI speeds on RPi3. - Fixed a problem where seg fault could occur in bcm2835_delayMicroseconds() if not running as root. Patch from Pok. - - \version 1.52 2017-02-03 - Added link to commercial license purchasing. - - \version 1.53 2018-01-14 - Added support for AUX SPI (SPI1) - Contributed by Arjan van Vught (http://www.raspberrypi-dmx.org/) - - \version 1.54 2018-01-17 - Fixed compile errors in new AUX spi code under some circumstances. - - \version 1.55 2018-01-20 - Fixed version numbers. - Fixed some warnings. - - \version 1.56 2018-06-10 - Supports bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST), after which SPI bytes are reversed on read or write. - Based on a suggestion by Damiano Benedetti. - - \version 1.57 2018-08-28 - Added SPI function bcm2835_spi_set_speed_hz(uint32_t speed_hz); - Contributed by Arjan van Vught (http://www.raspberrypi-dmx.org/) - - \version 1.58 2018-11-29 - Added examples/spiram, which shows how to use the included little library (spiram.c and spiram.h) - to read and write SPI RAM chips such as 23K256-I/P - - \version 1.59 2019-05-22 - Fixed a bug in bcm2835_i2c_read reported by Charles Hayward where a noisy I2C line cold cause a seg fault by - reading too many characters. - - \version 1.60 2019-07-23 - Applied patch from Mark Dootson for RPi 4 compatibility. Thanks Mark. Not tested here on RPi4, but others report it works. - Tested as still working correctly on earlier RPi models. Tested with Debian Buster on earlier models - - \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS -*/ - - -/* Defines for BCM2835 */ -#ifndef BCM2835_H -#define BCM2835_H - -#include - -#define BCM2835_VERSION 10060 /* Version 1.60 */ - -/* RPi 2 is ARM v7, and has DMB instruction for memory barriers. - Older RPis are ARM v6 and don't, so a coprocessor instruction must be used instead. - However, not all versions of gcc in all distros support the dmb assembler instruction even on conmpatible processors. - This test is so any ARMv7 or higher processors with suitable GCC will use DMB. -*/ -#if __ARM_ARCH >= 7 -#define BCM2835_HAVE_DMB -#endif - -/*! \defgroup constants Constants for passing to and from library functions - The values here are designed to be passed to various functions in the bcm2835 library. - @{ -*/ - -/*! This means pin HIGH, true, 3.3volts on a pin. */ -#define HIGH 0x1 -/*! This means pin LOW, false, 0volts on a pin. */ -#define LOW 0x0 - -/*! Return the minimum of 2 numbers */ -#ifndef MIN -#define MIN(a, b) (a < b ? a : b) -#endif - -/*! Speed of the core clock core_clk */ -#define BCM2835_CORE_CLK_HZ 250000000 /*!< 250 MHz */ - -/*! On all recent OSs, the base of the peripherals is read from a /proc file */ -#define BMC2835_RPI2_DT_FILENAME "/proc/device-tree/soc/ranges" - -/*! Physical addresses for various peripheral register sets - Base Physical Address of the BCM 2835 peripheral registers - Note this is different for the RPi2 BCM2836, where this is derived from /proc/device-tree/soc/ranges - If /proc/device-tree/soc/ranges exists on a RPi 1 OS, it would be expected to contain the - following numbers: -*/ -/*! Peripherals block base address on RPi 1 */ -#define BCM2835_PERI_BASE 0x20000000 -/*! Size of the peripherals block on RPi 1 */ -#define BCM2835_PERI_SIZE 0x01000000 -/*! Alternate base address for RPI 2 / 3 */ -#define BCM2835_RPI2_PERI_BASE 0x3F000000 -/*! Alternate base address for RPI 4 */ -#define BCM2835_RPI4_PERI_BASE 0xFE000000 -/*! Alternate size for RPI 4 */ -#define BCM2835_RPI4_PERI_SIZE 0x01800000 - -/*! Offsets for the bases of various peripherals within the peripherals block - / Base Address of the System Timer registers -*/ -#define BCM2835_ST_BASE 0x3000 -/*! Base Address of the Pads registers */ -#define BCM2835_GPIO_PADS 0x100000 -/*! Base Address of the Clock/timer registers */ -#define BCM2835_CLOCK_BASE 0x101000 -/*! Base Address of the GPIO registers */ -#define BCM2835_GPIO_BASE 0x200000 -/*! Base Address of the SPI0 registers */ -#define BCM2835_SPI0_BASE 0x204000 -/*! Base Address of the BSC0 registers */ -#define BCM2835_BSC0_BASE 0x205000 -/*! Base Address of the PWM registers */ -#define BCM2835_GPIO_PWM 0x20C000 -/*! Base Address of the AUX registers */ -#define BCM2835_AUX_BASE 0x215000 -/*! Base Address of the AUX_SPI1 registers */ -#define BCM2835_SPI1_BASE 0x215080 -/*! Base Address of the AUX_SPI2 registers */ -#define BCM2835_SPI2_BASE 0x2150C0 -/*! Base Address of the BSC1 registers */ -#define BCM2835_BSC1_BASE 0x804000 - - -/*! Physical address and size of the peripherals block - May be overridden on RPi2 -*/ -extern uint32_t *bcm2835_peripherals_base; -/*! Size of the peripherals block to be mapped */ -extern uint32_t bcm2835_peripherals_size; - -/*! Virtual memory address of the mapped peripherals block */ -extern uint32_t *bcm2835_peripherals; - -/*! Base of the ST (System Timer) registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_st; - -/*! Base of the GPIO registers. - Available after bcm2835_init has been called -*/ -extern volatile uint32_t *bcm2835_gpio; - -/*! Base of the PWM registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_pwm; - -/*! Base of the CLK registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_clk; - -/*! Base of the PADS registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_pads; - -/*! Base of the SPI0 registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_spi0; - -/*! Base of the BSC0 registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_bsc0; - -/*! Base of the BSC1 registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_bsc1; - -/*! Base of the AUX registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_aux; - -/*! Base of the SPI1 registers. - Available after bcm2835_init has been called (as root) -*/ -extern volatile uint32_t *bcm2835_spi1; - - -/*! \brief bcm2835RegisterBase - Register bases for bcm2835_regbase() -*/ -typedef enum { - BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */ - BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */ - BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */ - BCM2835_REGBASE_CLK = 4, /*!< Base of the CLK registers. */ - BCM2835_REGBASE_PADS = 5, /*!< Base of the PADS registers. */ - BCM2835_REGBASE_SPI0 = 6, /*!< Base of the SPI0 registers. */ - BCM2835_REGBASE_BSC0 = 7, /*!< Base of the BSC0 registers. */ - BCM2835_REGBASE_BSC1 = 8, /*!< Base of the BSC1 registers. */ - BCM2835_REGBASE_AUX = 9, /*!< Base of the AUX registers. */ - BCM2835_REGBASE_SPI1 = 10 /*!< Base of the SPI1 registers. */ -} bcm2835RegisterBase; - -/*! Size of memory page on RPi */ -#define BCM2835_PAGE_SIZE (4*1024) -/*! Size of memory block on RPi */ -#define BCM2835_BLOCK_SIZE (4*1024) - - -/* Defines for GPIO - The BCM2835 has 54 GPIO pins. - BCM2835 data sheet, Page 90 onwards. -*/ -/*! GPIO register offsets from BCM2835_GPIO_BASE. - Offsets into the GPIO Peripheral block in bytes per 6.1 Register View -*/ -#define BCM2835_GPFSEL0 0x0000 /*!< GPIO Function Select 0 */ -#define BCM2835_GPFSEL1 0x0004 /*!< GPIO Function Select 1 */ -#define BCM2835_GPFSEL2 0x0008 /*!< GPIO Function Select 2 */ -#define BCM2835_GPFSEL3 0x000c /*!< GPIO Function Select 3 */ -#define BCM2835_GPFSEL4 0x0010 /*!< GPIO Function Select 4 */ -#define BCM2835_GPFSEL5 0x0014 /*!< GPIO Function Select 5 */ -#define BCM2835_GPSET0 0x001c /*!< GPIO Pin Output Set 0 */ -#define BCM2835_GPSET1 0x0020 /*!< GPIO Pin Output Set 1 */ -#define BCM2835_GPCLR0 0x0028 /*!< GPIO Pin Output Clear 0 */ -#define BCM2835_GPCLR1 0x002c /*!< GPIO Pin Output Clear 1 */ -#define BCM2835_GPLEV0 0x0034 /*!< GPIO Pin Level 0 */ -#define BCM2835_GPLEV1 0x0038 /*!< GPIO Pin Level 1 */ -#define BCM2835_GPEDS0 0x0040 /*!< GPIO Pin Event Detect Status 0 */ -#define BCM2835_GPEDS1 0x0044 /*!< GPIO Pin Event Detect Status 1 */ -#define BCM2835_GPREN0 0x004c /*!< GPIO Pin Rising Edge Detect Enable 0 */ -#define BCM2835_GPREN1 0x0050 /*!< GPIO Pin Rising Edge Detect Enable 1 */ -#define BCM2835_GPFEN0 0x0058 /*!< GPIO Pin Falling Edge Detect Enable 0 */ -#define BCM2835_GPFEN1 0x005c /*!< GPIO Pin Falling Edge Detect Enable 1 */ -#define BCM2835_GPHEN0 0x0064 /*!< GPIO Pin High Detect Enable 0 */ -#define BCM2835_GPHEN1 0x0068 /*!< GPIO Pin High Detect Enable 1 */ -#define BCM2835_GPLEN0 0x0070 /*!< GPIO Pin Low Detect Enable 0 */ -#define BCM2835_GPLEN1 0x0074 /*!< GPIO Pin Low Detect Enable 1 */ -#define BCM2835_GPAREN0 0x007c /*!< GPIO Pin Async. Rising Edge Detect 0 */ -#define BCM2835_GPAREN1 0x0080 /*!< GPIO Pin Async. Rising Edge Detect 1 */ -#define BCM2835_GPAFEN0 0x0088 /*!< GPIO Pin Async. Falling Edge Detect 0 */ -#define BCM2835_GPAFEN1 0x008c /*!< GPIO Pin Async. Falling Edge Detect 1 */ -#define BCM2835_GPPUD 0x0094 /*!< GPIO Pin Pull-up/down Enable */ -#define BCM2835_GPPUDCLK0 0x0098 /*!< GPIO Pin Pull-up/down Enable Clock 0 */ -#define BCM2835_GPPUDCLK1 0x009c /*!< GPIO Pin Pull-up/down Enable Clock 1 */ - -/* 2711 has a different method for pin pull-up/down/enable */ -#define BCM2835_GPPUPPDN0 0x00e4 /* Pin pull-up/down for pins 15:0 */ -#define BCM2835_GPPUPPDN1 0x00e8 /* Pin pull-up/down for pins 31:16 */ -#define BCM2835_GPPUPPDN2 0x00ec /* Pin pull-up/down for pins 47:32 */ -#define BCM2835_GPPUPPDN3 0x00f0 /* Pin pull-up/down for pins 57:48 */ - -/*! \brief bcm2835PortFunction - Port function select modes for bcm2835_gpio_fsel() -*/ -typedef enum { - BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ - BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ - BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ - BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ - BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ - BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ - BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ - BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ - BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ -} bcm2835FunctionSelect; - -/*! \brief bcm2835PUDControl - Pullup/Pulldown defines for bcm2835_gpio_pud() -*/ -typedef enum { - BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ - BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ - BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ -} bcm2835PUDControl; - -/* need a value for pud functions that can't work unless RPI 4 */ -#define BCM2835_GPIO_PUD_ERROR 0x08 - -/*! Pad control register offsets from BCM2835_GPIO_PADS */ -#define BCM2835_PADS_GPIO_0_27 0x002c /*!< Pad control register for pads 0 to 27 */ -#define BCM2835_PADS_GPIO_28_45 0x0030 /*!< Pad control register for pads 28 to 45 */ -#define BCM2835_PADS_GPIO_46_53 0x0034 /*!< Pad control register for pads 46 to 53 */ - -/*! Pad Control masks */ -#define BCM2835_PAD_PASSWRD (0x5A << 24) /*!< Password to enable setting pad mask */ -#define BCM2835_PAD_SLEW_RATE_UNLIMITED 0x10 /*!< Slew rate unlimited */ -#define BCM2835_PAD_HYSTERESIS_ENABLED 0x08 /*!< Hysteresis enabled */ -#define BCM2835_PAD_DRIVE_2mA 0x00 /*!< 2mA drive current */ -#define BCM2835_PAD_DRIVE_4mA 0x01 /*!< 4mA drive current */ -#define BCM2835_PAD_DRIVE_6mA 0x02 /*!< 6mA drive current */ -#define BCM2835_PAD_DRIVE_8mA 0x03 /*!< 8mA drive current */ -#define BCM2835_PAD_DRIVE_10mA 0x04 /*!< 10mA drive current */ -#define BCM2835_PAD_DRIVE_12mA 0x05 /*!< 12mA drive current */ -#define BCM2835_PAD_DRIVE_14mA 0x06 /*!< 14mA drive current */ -#define BCM2835_PAD_DRIVE_16mA 0x07 /*!< 16mA drive current */ - -/*! \brief bcm2835PadGroup - Pad group specification for bcm2835_gpio_pad() -*/ -typedef enum { - BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ - BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ - BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ -} bcm2835PadGroup; - -/*! \brief GPIO Pin Numbers - - Here we define Raspberry Pin GPIO pins on P1 in terms of the underlying BCM GPIO pin numbers. - These can be passed as a pin number to any function requiring a pin. - Not all pins on the RPi 26 bin IDE plug are connected to GPIO pins - and some can adopt an alternate function. - RPi version 2 has some slightly different pinouts, and these are values RPI_V2_*. - RPi B+ has yet differnet pinouts and these are defined in RPI_BPLUS_*. - At bootup, pins 8 and 10 are set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively - When SPI0 is in use (ie after bcm2835_spi_begin()), SPI0 pins are dedicated to SPI - and cant be controlled independently. - If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these - symbolic names -*/ -typedef enum { - RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ - RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ - RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ - RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */ - RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */ - RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */ - RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */ - RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */ - RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */ - RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */ - RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */ - RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */ - RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */ - RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */ - RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */ - RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */ - - /* RPi Version 2 */ - RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */ - RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */ - RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */ - RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */ - RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */ - RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */ - RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */ - RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */ - RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */ - RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */ - RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */ - RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */ - RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */ - RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */ - RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */ - RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */ - RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */ - RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ - RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ - RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ - RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35, can be PWM channel 1 in ALT FUN 5 */ - RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ - RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ - RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ - RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */ - - /* RPi Version 2, new plug P5 */ - RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */ - RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */ - RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */ - RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */ - - /* RPi B+ J8 header, also RPi 2 40 pin GPIO header */ - RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */ - RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */ - RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */ - RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */ - RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */ - RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */ - RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */ - RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */ - RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */ - RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */ - RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */ - RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */ - RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */ - RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */ - RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */ - RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */ - RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */ - RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ - RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ - RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ - RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, can be PWM channel 1 in ALT FUN 5 */ - RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ - RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ - RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ - RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */ -} RPiGPIOPin; - -/* Defines for AUX - GPIO register offsets from BCM2835_AUX_BASE. -*/ -#define BCM2835_AUX_IRQ 0x0000 /*!< xxx */ -#define BCM2835_AUX_ENABLE 0x0004 /*!< */ - -#define BCM2835_AUX_ENABLE_UART1 0x01 /*!< */ -#define BCM2835_AUX_ENABLE_SPI0 0x02 /*!< SPI0 (SPI1 in the device) */ -#define BCM2835_AUX_ENABLE_SPI1 0x04 /*!< SPI1 (SPI2 in the device) */ - - -#define BCM2835_AUX_SPI_CNTL0 0x0000 /*!< */ -#define BCM2835_AUX_SPI_CNTL1 0x0004 /*!< */ -#define BCM2835_AUX_SPI_STAT 0x0008 /*!< */ -#define BCM2835_AUX_SPI_PEEK 0x000C /*!< Read but do not take from FF */ -#define BCM2835_AUX_SPI_IO 0x0020 /*!< Write = TX, read=RX */ -#define BCM2835_AUX_SPI_TXHOLD 0x0030 /*!< Write = TX keep CS, read=RX */ - -#define BCM2835_AUX_SPI_CLOCK_MIN 30500 /*!< 30,5kHz */ -#define BCM2835_AUX_SPI_CLOCK_MAX 125000000 /*!< 125Mhz */ - -#define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF /*!< */ -#define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20 /*!< */ - -#define BCM2835_AUX_SPI_CNTL0_CS0_N 0x000C0000 /*!< CS 0 low */ -#define BCM2835_AUX_SPI_CNTL0_CS1_N 0x000A0000 /*!< CS 1 low */ -#define BCM2835_AUX_SPI_CNTL0_CS2_N 0x00060000 /*!< CS 2 low */ - -#define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F /*!< */ - -#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 /*!< */ -#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080 /*!< */ -#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040 /*!< */ -#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 /*!< */ -#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 /*!< */ - -#define BCM2835_AUX_SPI_STAT_TX_LVL 0xFF000000 /*!< */ -#define BCM2835_AUX_SPI_STAT_RX_LVL 0x00FF0000 /*!< */ -#define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400 /*!< */ -#define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200 /*!< */ -#define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100 /*!< */ -#define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080 /*!< */ -#define BCM2835_AUX_SPI_STAT_BUSY 0x00000040 /*!< */ -#define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F /*!< */ - -/* Defines for SPI - GPIO register offsets from BCM2835_SPI0_BASE. - Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map -*/ -#define BCM2835_SPI0_CS 0x0000 /*!< SPI Master Control and Status */ -#define BCM2835_SPI0_FIFO 0x0004 /*!< SPI Master TX and RX FIFOs */ -#define BCM2835_SPI0_CLK 0x0008 /*!< SPI Master Clock Divider */ -#define BCM2835_SPI0_DLEN 0x000c /*!< SPI Master Data Length */ -#define BCM2835_SPI0_LTOH 0x0010 /*!< SPI LOSSI mode TOH */ -#define BCM2835_SPI0_DC 0x0014 /*!< SPI DMA DREQ Controls */ - -/* Register masks for SPI0_CS */ -#define BCM2835_SPI0_CS_LEN_LONG 0x02000000 /*!< Enable Long data word in Lossi mode if DMA_LEN is set */ -#define BCM2835_SPI0_CS_DMA_LEN 0x01000000 /*!< Enable DMA mode in Lossi mode */ -#define BCM2835_SPI0_CS_CSPOL2 0x00800000 /*!< Chip Select 2 Polarity */ -#define BCM2835_SPI0_CS_CSPOL1 0x00400000 /*!< Chip Select 1 Polarity */ -#define BCM2835_SPI0_CS_CSPOL0 0x00200000 /*!< Chip Select 0 Polarity */ -#define BCM2835_SPI0_CS_RXF 0x00100000 /*!< RXF - RX FIFO Full */ -#define BCM2835_SPI0_CS_RXR 0x00080000 /*!< RXR RX FIFO needs Reading (full) */ -#define BCM2835_SPI0_CS_TXD 0x00040000 /*!< TXD TX FIFO can accept Data */ -#define BCM2835_SPI0_CS_RXD 0x00020000 /*!< RXD RX FIFO contains Data */ -#define BCM2835_SPI0_CS_DONE 0x00010000 /*!< Done transfer Done */ -#define BCM2835_SPI0_CS_TE_EN 0x00008000 /*!< Unused */ -#define BCM2835_SPI0_CS_LMONO 0x00004000 /*!< Unused */ -#define BCM2835_SPI0_CS_LEN 0x00002000 /*!< LEN LoSSI enable */ -#define BCM2835_SPI0_CS_REN 0x00001000 /*!< REN Read Enable */ -#define BCM2835_SPI0_CS_ADCS 0x00000800 /*!< ADCS Automatically Deassert Chip Select */ -#define BCM2835_SPI0_CS_INTR 0x00000400 /*!< INTR Interrupt on RXR */ -#define BCM2835_SPI0_CS_INTD 0x00000200 /*!< INTD Interrupt on Done */ -#define BCM2835_SPI0_CS_DMAEN 0x00000100 /*!< DMAEN DMA Enable */ -#define BCM2835_SPI0_CS_TA 0x00000080 /*!< Transfer Active */ -#define BCM2835_SPI0_CS_CSPOL 0x00000040 /*!< Chip Select Polarity */ -#define BCM2835_SPI0_CS_CLEAR 0x00000030 /*!< Clear FIFO Clear RX and TX */ -#define BCM2835_SPI0_CS_CLEAR_RX 0x00000020 /*!< Clear FIFO Clear RX */ -#define BCM2835_SPI0_CS_CLEAR_TX 0x00000010 /*!< Clear FIFO Clear TX */ -#define BCM2835_SPI0_CS_CPOL 0x00000008 /*!< Clock Polarity */ -#define BCM2835_SPI0_CS_CPHA 0x00000004 /*!< Clock Phase */ -#define BCM2835_SPI0_CS_CS 0x00000003 /*!< Chip Select */ - -/*! \brief bcm2835SPIBitOrder SPI Bit order - Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() -*/ -typedef enum { - BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ - BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ -} bcm2835SPIBitOrder; - -/*! \brief SPI Data mode - Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() -*/ -typedef enum { - BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ - BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ - BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ - BCM2835_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ -} bcm2835SPIMode; - -/*! \brief bcm2835SPIChipSelect - Specify the SPI chip select pin(s) -*/ -typedef enum { - BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */ - BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */ - BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ - BCM2835_SPI_CS_NONE = 3 /*!< No CS, control it yourself */ -} bcm2835SPIChipSelect; - -/*! \brief bcm2835SPIClockDivider - Specifies the divider used to generate the SPI clock from the system clock. - Figures below give the divider, clock period and clock frequency. - Clock divided is based on nominal core clock rate of 250MHz on RPi1 and RPi2, and 400MHz on RPi3. - It is reported that (contrary to the documentation) any even divider may used. - The frequencies shown for each divider have been confirmed by measurement on RPi1 and RPi2. - The system clock frequency on RPi3 is different, so the frequency you get from a given divider will be different. - See comments in 'SPI Pins' for information about reliable SPI speeds. - Note: it is possible to change the core clock rate of the RPi 3 back to 250MHz, by putting - \code - core_freq=250 - \endcode - in the config.txt -*/ -typedef enum { - BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */ - BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/ - BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */ -} bcm2835SPIClockDivider; - -/* Defines for I2C - GPIO register offsets from BCM2835_BSC*_BASE. - Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map -*/ -#define BCM2835_BSC_C 0x0000 /*!< BSC Master Control */ -#define BCM2835_BSC_S 0x0004 /*!< BSC Master Status */ -#define BCM2835_BSC_DLEN 0x0008 /*!< BSC Master Data Length */ -#define BCM2835_BSC_A 0x000c /*!< BSC Master Slave Address */ -#define BCM2835_BSC_FIFO 0x0010 /*!< BSC Master Data FIFO */ -#define BCM2835_BSC_DIV 0x0014 /*!< BSC Master Clock Divider */ -#define BCM2835_BSC_DEL 0x0018 /*!< BSC Master Data Delay */ -#define BCM2835_BSC_CLKT 0x001c /*!< BSC Master Clock Stretch Timeout */ - -/* Register masks for BSC_C */ -#define BCM2835_BSC_C_I2CEN 0x00008000 /*!< I2C Enable, 0 = disabled, 1 = enabled */ -#define BCM2835_BSC_C_INTR 0x00000400 /*!< Interrupt on RX */ -#define BCM2835_BSC_C_INTT 0x00000200 /*!< Interrupt on TX */ -#define BCM2835_BSC_C_INTD 0x00000100 /*!< Interrupt on DONE */ -#define BCM2835_BSC_C_ST 0x00000080 /*!< Start transfer, 1 = Start a new transfer */ -#define BCM2835_BSC_C_CLEAR_1 0x00000020 /*!< Clear FIFO Clear */ -#define BCM2835_BSC_C_CLEAR_2 0x00000010 /*!< Clear FIFO Clear */ -#define BCM2835_BSC_C_READ 0x00000001 /*!< Read transfer */ - -/* Register masks for BSC_S */ -#define BCM2835_BSC_S_CLKT 0x00000200 /*!< Clock stretch timeout */ -#define BCM2835_BSC_S_ERR 0x00000100 /*!< ACK error */ -#define BCM2835_BSC_S_RXF 0x00000080 /*!< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ -#define BCM2835_BSC_S_TXE 0x00000040 /*!< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ -#define BCM2835_BSC_S_RXD 0x00000020 /*!< RXD FIFO contains data */ -#define BCM2835_BSC_S_TXD 0x00000010 /*!< TXD FIFO can accept data */ -#define BCM2835_BSC_S_RXR 0x00000008 /*!< RXR FIFO needs reading (full) */ -#define BCM2835_BSC_S_TXW 0x00000004 /*!< TXW FIFO needs writing (full) */ -#define BCM2835_BSC_S_DONE 0x00000002 /*!< Transfer DONE */ -#define BCM2835_BSC_S_TA 0x00000001 /*!< Transfer Active */ - -#define BCM2835_BSC_FIFO_SIZE 16 /*!< BSC FIFO size */ - -/*! \brief bcm2835I2CClockDivider - Specifies the divider used to generate the I2C clock from the system clock. - Clock divided is based on nominal base clock rate of 250MHz -*/ -typedef enum { - BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ - BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ - BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ - BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ -} bcm2835I2CClockDivider; - -/*! \brief bcm2835I2CReasonCodes - Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. -*/ -typedef enum { - BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ - BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ - BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ - BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ -} bcm2835I2CReasonCodes; - -/* Defines for ST - GPIO register offsets from BCM2835_ST_BASE. - Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers - The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter. - BCM2835_ST_CLO is the System Timer Counter Lower bits register. - The system timer free-running counter lower register is a read-only register that returns the current value - of the lower 32-bits of the free running counter. - BCM2835_ST_CHI is the System Timer Counter Upper bits register. - The system timer free-running counter upper register is a read-only register that returns the current value - of the upper 32-bits of the free running counter. -*/ -#define BCM2835_ST_CS 0x0000 /*!< System Timer Control/Status */ -#define BCM2835_ST_CLO 0x0004 /*!< System Timer Counter Lower 32 bits */ -#define BCM2835_ST_CHI 0x0008 /*!< System Timer Counter Upper 32 bits */ - -/*! @} */ - - -/* Defines for PWM, word offsets (ie 4 byte multiples) */ -#define BCM2835_PWM_CONTROL 0 -#define BCM2835_PWM_STATUS 1 -#define BCM2835_PWM_DMAC 2 -#define BCM2835_PWM0_RANGE 4 -#define BCM2835_PWM0_DATA 5 -#define BCM2835_PWM_FIF1 6 -#define BCM2835_PWM1_RANGE 8 -#define BCM2835_PWM1_DATA 9 - -/* Defines for PWM Clock, word offsets (ie 4 byte multiples) */ -#define BCM2835_PWMCLK_CNTL 40 -#define BCM2835_PWMCLK_DIV 41 -#define BCM2835_PWM_PASSWRD (0x5A << 24) /*!< Password to enable setting PWM clock */ - -#define BCM2835_PWM1_MS_MODE 0x8000 /*!< Run in Mark/Space mode */ -#define BCM2835_PWM1_USEFIFO 0x2000 /*!< Data from FIFO */ -#define BCM2835_PWM1_REVPOLAR 0x1000 /*!< Reverse polarity */ -#define BCM2835_PWM1_OFFSTATE 0x0800 /*!< Ouput Off state */ -#define BCM2835_PWM1_REPEATFF 0x0400 /*!< Repeat last value if FIFO empty */ -#define BCM2835_PWM1_SERIAL 0x0200 /*!< Run in serial mode */ -#define BCM2835_PWM1_ENABLE 0x0100 /*!< Channel Enable */ - -#define BCM2835_PWM0_MS_MODE 0x0080 /*!< Run in Mark/Space mode */ -#define BCM2835_PWM_CLEAR_FIFO 0x0040 /*!< Clear FIFO */ -#define BCM2835_PWM0_USEFIFO 0x0020 /*!< Data from FIFO */ -#define BCM2835_PWM0_REVPOLAR 0x0010 /*!< Reverse polarity */ -#define BCM2835_PWM0_OFFSTATE 0x0008 /*!< Ouput Off state */ -#define BCM2835_PWM0_REPEATFF 0x0004 /*!< Repeat last value if FIFO empty */ -#define BCM2835_PWM0_SERIAL 0x0002 /*!< Run in serial mode */ -#define BCM2835_PWM0_ENABLE 0x0001 /*!< Channel Enable */ - -/*! \brief bcm2835PWMClockDivider - Specifies the divider used to generate the PWM clock from the system clock. - Figures below give the divider, clock period and clock frequency. - Clock divided is based on nominal PWM base clock rate of 19.2MHz - The frequencies shown for each divider have been confirmed by measurement -*/ -typedef enum { - BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */ - BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */ - BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */ - BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */ - BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */ - BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */ - BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */ - BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */ - BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */ - BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */ - BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */ - BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */ -} bcm2835PWMClockDivider; - -/* Historical name compatibility */ -#ifndef BCM2835_NO_DELAY_COMPATIBILITY -#define delay(x) bcm2835_delay(x) -#define delayMicroseconds(x) bcm2835_delayMicroseconds(x) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*! \defgroup init Library initialisation and management - These functions allow you to intialise and control the bcm2835 library - @{ -*/ - -/*! Initialise the library by opening /dev/mem (if you are root) - or /dev/gpiomem (if you are not) - and getting pointers to the - internal memory for BCM 2835 device registers. You must call this (successfully) - before calling any other - functions in this library (except bcm2835_set_debug). - If bcm2835_init() fails by returning 0, - calling any other function may result in crashes or other failures. - If bcm2835_init() succeeds but you are not running as root, then only gpio operations - are permitted, and calling any other functions may result in crashes or other failures. . - Prints messages to stderr in case of errors. - \return 1 if successful else 0 -*/ -extern int bcm2835_init(void); - -/*! Close the library, deallocating any allocated memory and closing /dev/mem - \return 1 if successful else 0 -*/ -extern int bcm2835_close(void); - -/*! Sets the debug level of the library. - A value of 1 prevents mapping to /dev/mem, and makes the library print out - what it would do, rather than accessing the GPIO registers. - A value of 0, the default, causes normal operation. - Call this before calling bcm2835_init(); - \param[in] debug The new debug level. 1 means debug -*/ -extern void bcm2835_set_debug(uint8_t debug); - -/*! Returns the version number of the library, same as BCM2835_VERSION - \return the current library version number -*/ -extern unsigned int bcm2835_version(void); - -/*! @} */ - -/*! \defgroup lowlevel Low level register access - These functions provide low level register access, and should not generally - need to be used - - @{ -*/ - -/*! Gets the base of a register - \param[in] regbase You can use one of the common values BCM2835_REGBASE_* - in \ref bcm2835RegisterBase - \return the register base - \sa Physical Addresses -*/ -extern uint32_t* bcm2835_regbase(uint8_t regbase); - -/*! Reads 32 bit value from a peripheral address WITH a memory barrier before and after each read. - This is safe, but slow. The MB before protects this read from any in-flight reads that didn't - use a MB. The MB after protects subsequent reads from another peripheral. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \return the value read from the 32 bit register - \sa Physical Addresses -*/ -extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); - -/*! Reads 32 bit value from a peripheral address WITHOUT the read barriers - You should only use this when: - o your code has previously called bcm2835_peri_read() for a register - within the same peripheral, and no read or write to another peripheral has occurred since. - o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \return the value read from the 32 bit register - \sa Physical Addresses -*/ -extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); - - -/*! Writes 32 bit value from a peripheral address WITH a memory barrier before and after each write - This is safe, but slow. The MB before ensures that any in-flight write to another peripheral - completes before this write is issued. The MB after ensures that subsequent reads and writes - to another peripheral will see the effect of this write. - - This is a tricky optimization; if you aren't sure, use the barrier version. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write - \sa Physical Addresses -*/ -extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); - -/*! Writes 32 bit value from a peripheral address without the write barrier - You should only use this when: - o your code has previously called bcm2835_peri_write() for a register - within the same peripheral, and no other peripheral access has occurred since. - o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - - This is a tricky optimization; if you aren't sure, use the barrier version. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write - \sa Physical Addresses -*/ -extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); - -/*! Alters a number of bits in a 32 peripheral regsiter. - It reads the current valu and then alters the bits defines as 1 in mask, - according to the bit value in value. - All other bits that are 0 in the mask are unaffected. - Use this to alter a subset of the bits in a register. - Memory barriers are used. Note that this is not atomic; an interrupt - routine can cause unexpected results. - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write, masked in by mask. - \param[in] mask Bitmask that defines the bits that will be altered in the register. - \sa Physical Addresses -*/ -extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); -/*! @} end of lowlevel */ - -/*! \defgroup gpio GPIO register access - These functions allow you to control the GPIO interface. You can set the - function of each GPIO pin, read the input state and set the output state. - @{ -*/ - -/*! Sets the Function Select register for the given pin, which configures - the pin as Input, Output or one of the 6 alternate functions. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect -*/ -extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); - -/*! Sets the specified pin output to - HIGH. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \sa bcm2835_gpio_write() -*/ -extern void bcm2835_gpio_set(uint8_t pin); - -/*! Sets the specified pin output to - LOW. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \sa bcm2835_gpio_write() -*/ -extern void bcm2835_gpio_clr(uint8_t pin); - -/*! Sets any of the first 32 GPIO output pins specified in the mask to - HIGH. - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \sa bcm2835_gpio_write_multi() -*/ -extern void bcm2835_gpio_set_multi(uint32_t mask); - -/*! Sets any of the first 32 GPIO output pins specified in the mask to - LOW. - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \sa bcm2835_gpio_write_multi() -*/ -extern void bcm2835_gpio_clr_multi(uint32_t mask); - -/*! Reads the current level on the specified - pin and returns either HIGH or LOW. Works whether or not the pin - is an input or an output. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \return the current level either HIGH or LOW -*/ -extern uint8_t bcm2835_gpio_lev(uint8_t pin); - -/*! Event Detect Status. - Tests whether the specified pin has detected a level or edge - as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), - bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). - Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \return HIGH if the event detect status for the given pin is true. -*/ -extern uint8_t bcm2835_gpio_eds(uint8_t pin); - -/*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in - the mask have detected a level or edge. - \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \return Mask of pins HIGH if the event detect status for the given pin is true. -*/ -extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask); - -/*! Sets the Event Detect Status register for a given pin to 1, - which has the effect of clearing the flag. Use this afer seeing - an Event Detect Status on the pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_set_eds(uint8_t pin); - -/*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which - is set in the mask. - \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) -*/ -extern void bcm2835_gpio_set_eds_multi(uint32_t mask); - -/*! Enable Rising Edge Detect Enable for the specified pin. - When a rising edge is detected, sets the appropriate pin in Event Detect Status. - The GPRENn registers use - synchronous edge detection. This means the input signal is sampled using the - system clock and then it is looking for a ?011? pattern on the sampled signal. This - has the effect of suppressing glitches. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_ren(uint8_t pin); - -/*! Disable Rising Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_clr_ren(uint8_t pin); - -/*! Enable Falling Edge Detect Enable for the specified pin. - When a falling edge is detected, sets the appropriate pin in Event Detect Status. - The GPRENn registers use - synchronous edge detection. This means the input signal is sampled using the - system clock and then it is looking for a ?100? pattern on the sampled signal. This - has the effect of suppressing glitches. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_fen(uint8_t pin); - -/*! Disable Falling Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_clr_fen(uint8_t pin); - -/*! Enable High Detect Enable for the specified pin. - When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_hen(uint8_t pin); - -/*! Disable High Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_clr_hen(uint8_t pin); - -/*! Enable Low Detect Enable for the specified pin. - When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_len(uint8_t pin); - -/*! Disable Low Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_clr_len(uint8_t pin); - -/*! Enable Asynchronous Rising Edge Detect Enable for the specified pin. - When a rising edge is detected, sets the appropriate pin in Event Detect Status. - Asynchronous means the incoming signal is not sampled by the system clock. As such - rising edges of very short duration can be detected. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_aren(uint8_t pin); - -/*! Disable Asynchronous Rising Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_clr_aren(uint8_t pin); - -/*! Enable Asynchronous Falling Edge Detect Enable for the specified pin. - When a falling edge is detected, sets the appropriate pin in Event Detect Status. - Asynchronous means the incoming signal is not sampled by the system clock. As such - falling edges of very short duration can be detected. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_afen(uint8_t pin); - -/*! Disable Asynchronous Falling Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ -extern void bcm2835_gpio_clr_afen(uint8_t pin); - -/*! Sets the Pull-up/down register for the given pin. This is - used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. - However, it is usually more convenient to use bcm2835_gpio_set_pud(). - \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - On the RPI 4, although this function and bcm2835_gpio_pudclk() are supported for backward - compatibility, new code should always use bcm2835_gpio_set_pud(). - \sa bcm2835_gpio_set_pud() -*/ -extern void bcm2835_gpio_pud(uint8_t pud); - -/*! Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. - LOW to remove the clock. - - On the RPI 4, although this function and bcm2835_gpio_pud() are supported for backward - compatibility, new code should always use bcm2835_gpio_set_pud(). - - \sa bcm2835_gpio_set_pud() -*/ -extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); - -/*! Reads and returns the Pad Control for the given GPIO group. - Caution: requires root access. - \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup -*/ -extern uint32_t bcm2835_gpio_pad(uint8_t group); - -/*! Sets the Pad Control for the given GPIO group. - Caution: requires root access. - \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note - that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this - is automatically included. -*/ -extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); - -/*! Delays for the specified number of milliseconds. - Uses nanosleep(), and therefore does not use CPU until the time is up. - However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - If the interval specified in req is not an exact multiple of the granularity - underlying clock (see time(7)), then the interval will be - rounded up to the next multiple. Furthermore, after the sleep completes, - there may still be a delay before the CPU becomes free to once - again execute the calling thread. - \param[in] millis Delay in milliseconds -*/ -extern void bcm2835_delay (unsigned int millis); - -/*! Delays for the specified number of microseconds. - Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, - However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - If the interval specified in req is not an exact multiple of the granularity - underlying clock (see time(7)), then the interval will be - rounded up to the next multiple. Furthermore, after the sleep completes, - there may still be a delay before the CPU becomes free to once - again execute the calling thread. - For times less than about 450 microseconds, uses a busy wait on the System Timer. - It is reported that a delay of 0 microseconds on RaspberryPi will in fact - result in a delay of about 80 microseconds. Your mileage may vary. - \param[in] micros Delay in microseconds -*/ -extern void bcm2835_delayMicroseconds (uint64_t micros); - -/*! Sets the output state of the specified pin - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] on HIGH sets the output to HIGH and LOW to LOW. -*/ -extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); - -/*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \param[in] on HIGH sets the output to HIGH and LOW to LOW. -*/ -extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); - -/*! Sets the first 32 GPIO output pins specified in the mask to the value given by value - \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) -*/ -extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); - -/*! Sets the Pull-up/down mode for the specified pin. This is more convenient than - clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl -*/ -extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); - -/*! On the BCM2711 based RPI 4, gets the current Pull-up/down mode for the specified pin. - Returns one of BCM2835_GPIO_PUD_* from bcm2835PUDControl. - On earlier RPI versions not based on the BCM2711, returns BCM2835_GPIO_PUD_ERROR - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. -*/ - -extern uint8_t bcm2835_gpio_get_pud(uint8_t pin); - -/*! @} */ - -/*! \defgroup spi SPI access - These functions let you use SPI0 (Serial Peripheral Interface) to - interface with an external SPI device. - @{ -*/ - -/*! Start SPI operations. - Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - to alternate function ALT0, which enables those pins for SPI interface. - You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to - their default functions. - \sa bcm2835_spi_end() - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) -*/ -extern int bcm2835_spi_begin(void); - -/*! End SPI operations. - SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - are returned to their default INPUT behaviour. -*/ -extern void bcm2835_spi_end(void); - -/*! Sets the SPI bit order - Set the bit order to be used for transmit and receive. The bcm2835 SPI0 only supports BCM2835_SPI_BIT_ORDER_MSB, - so if you select BCM2835_SPI_BIT_ORDER_LSB, the bytes will be reversed in software. - The library defaults to BCM2835_SPI_BIT_ORDER_MSB. - \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, - see \ref bcm2835SPIBitOrder -*/ -extern void bcm2835_spi_setBitOrder(uint8_t order); - -/*! Sets the SPI clock divider and therefore the - SPI clock speed. - \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, - see \ref bcm2835SPIClockDivider -*/ -extern void bcm2835_spi_setClockDivider(uint16_t divider); - -/*! Sets the SPI clock divider by converting the speed parameter to - the equivalent SPI clock divider. ( see \sa bcm2835_spi_setClockDivider) - \param[in] speed_hz The desired SPI clock speed in Hz -*/ -extern void bcm2835_spi_set_speed_hz(uint32_t speed_hz); - -/*! Sets the SPI data mode - Sets the clock polariy and phase - \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, - see \ref bcm2835SPIMode -*/ -extern void bcm2835_spi_setDataMode(uint8_t mode); - -/*! Sets the chip select pin(s) - When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the - transfer. - \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. - One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect -*/ -extern void bcm2835_spi_chipSelect(uint8_t cs); - -/*! Sets the chip select pin polarity for a given pin - When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) - will be asserted to the - value given by active. When transfers are not happening, the chip select pin(s) - return to the complement (inactive) value. - \param[in] cs The chip select pin to affect - \param[in] active Whether the chip select pin is to be active HIGH -*/ -extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); - -/*! Transfers one byte to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. - Returns the read data byte from the slave. - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] value The 8 bit data byte to write to MOSI - \return The 8 bit byte simultaneously read from MISO - \sa bcm2835_spi_transfern() -*/ -extern uint8_t bcm2835_spi_transfer(uint8_t value); - -/*! Transfers any number of bytes to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. - The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] tbuf Buffer of bytes to send. - \param[out] rbuf Received bytes will by put in this buffer - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received - \sa bcm2835_spi_transfer() -*/ -extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); - -/*! Transfers any number of bytes to and from the currently selected SPI slave - using bcm2835_spi_transfernb. - The returned data from the slave replaces the transmitted data in the buffer. - \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - \sa bcm2835_spi_transfer() -*/ -extern void bcm2835_spi_transfern(char* buf, uint32_t len); - -/*! Transfers any number of bytes to the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to send -*/ -extern void bcm2835_spi_writenb(const char* buf, uint32_t len); - -/*! Transfers half-word to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. - Returns the read data byte from the slave. - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] data The 8 bit data byte to write to MOSI - \sa bcm2835_spi_writenb() -*/ -extern void bcm2835_spi_write(uint16_t data); - -/*! Start AUX SPI operations. - Forces RPi AUX SPI pins P1-36 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2) - to alternate function ALT4, which enables those pins for SPI interface. - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) -*/ -extern int bcm2835_aux_spi_begin(void); - -/*! End AUX SPI operations. - SPI1 pins P1-36 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2) - are returned to their default INPUT behaviour. - */ -extern void bcm2835_aux_spi_end(void); - -/*! Sets the AUX SPI clock divider and therefore the AUX SPI clock speed. - \param[in] divider The desired AUX SPI clock divider. -*/ -extern void bcm2835_aux_spi_setClockDivider(uint16_t divider); - -/*! - * Calculates the input for \sa bcm2835_aux_spi_setClockDivider - * @param speed_hz A value between \sa BCM2835_AUX_SPI_CLOCK_MIN and \sa BCM2835_AUX_SPI_CLOCK_MAX - * @return Input for \sa bcm2835_aux_spi_setClockDivider - */ -extern uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz); - -/*! Transfers half-word to and from the AUX SPI slave. - Asserts the currently selected CS pins during the transfer. - \param[in] data The 8 bit data byte to write to MOSI - \return The 8 bit byte simultaneously read from MISO - \sa bcm2835_spi_transfern() -*/ -extern void bcm2835_aux_spi_write(uint16_t data); - -/*! Transfers any number of bytes to the AUX SPI slave. - Asserts the CE2 pin during the transfer. - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send -*/ -extern void bcm2835_aux_spi_writenb(const char *buf, uint32_t len); - -/*! Transfers any number of bytes to and from the AUX SPI slave - using bcm2835_aux_spi_transfernb. - The returned data from the slave replaces the transmitted data in the buffer. - \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - \sa bcm2835_aux_spi_transfer() -*/ -extern void bcm2835_aux_spi_transfern(char *buf, uint32_t len); - -/*! Transfers any number of bytes to and from the AUX SPI slave. - Asserts the CE2 pin during the transfer. - Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. - The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long - \param[in] tbuf Buffer of bytes to send. - \param[out] rbuf Received bytes will by put in this buffer - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received -*/ -extern void bcm2835_aux_spi_transfernb(const char *tbuf, char *rbuf, uint32_t len); - -/*! @} */ - -/*! \defgroup i2c I2C access - These functions let you use I2C (The Broadcom Serial Control bus with the Philips - I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. - @{ -*/ - -/*! Start I2C operations. - Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) - to alternate function ALT0, which enables those pins for I2C interface. - You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to - their default functions - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - \sa bcm2835_i2c_end() -*/ -extern int bcm2835_i2c_begin(void); - -/*! End I2C operations. - I2C pins P1-03 (SDA) and P1-05 (SCL) - are returned to their default INPUT behaviour. -*/ -extern void bcm2835_i2c_end(void); - -/*! Sets the I2C slave address. - \param[in] addr The I2C slave address. -*/ -extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); - -/*! Sets the I2C clock divider and therefore the I2C clock speed. - \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, - see \ref bcm2835I2CClockDivider -*/ -extern void bcm2835_i2c_setClockDivider(uint16_t divider); - -/*! Sets the I2C clock divider by converting the baudrate parameter to - the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) - For the I2C standard 100khz you would set baudrate to 100000 - The use of baudrate corresponds to its use in the I2C kernel device - driver. (Of course, bcm2835 has nothing to do with the kernel driver) -*/ -extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); - -/*! Transfers any number of bytes to the currently selected I2C slave. - (as previously set by \sa bcm2835_i2c_setSlaveAddress) - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. - \return reason see \ref bcm2835I2CReasonCodes -*/ -extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); - -/*! Transfers any number of bytes from the currently selected I2C slave. - (as previously set by \sa bcm2835_i2c_setSlaveAddress) - \param[in] buf Buffer of bytes to receive. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - \return reason see \ref bcm2835I2CReasonCodes -*/ -extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); - -/*! Allows reading from I2C slaves that require a repeated start (without any prior stop) - to read after the required slave register has been set. For example, the popular - MPL3115A2 pressure and temperature sensor. Note that your device must support or - require this mode. If your device does not require this mode then the standard - combined: - \sa bcm2835_i2c_write - \sa bcm2835_i2c_read - are a better choice. - Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - \param[in] regaddr Buffer containing the slave register you wish to read from. - \param[in] buf Buffer of bytes to receive. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - \return reason see \ref bcm2835I2CReasonCodes -*/ -extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); - -/*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated - start (with no prior stop) and reading a response. - Necessary for devices that require such behavior, such as the MLX90620. - Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - \param[in] cmds Buffer containing the bytes to send before the repeated start condition. - \param[in] cmds_len Number of bytes to send from cmds buffer - \param[in] buf Buffer of bytes to receive. - \param[in] buf_len Number of bytes to receive in the buf buffer. - \return reason see \ref bcm2835I2CReasonCodes -*/ -extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, - uint32_t buf_len); - -/*! @} */ - -/*! \defgroup st System Timer access - Allows access to and delays using the System Timer Counter. - @{ -*/ - -/*! Read the System Timer Counter register. - \return the value read from the System Timer Counter Lower 32 bits register -*/ -extern uint64_t bcm2835_st_read(void); - -/*! Delays for the specified number of microseconds with offset. - \param[in] offset_micros Offset in microseconds - \param[in] micros Delay in microseconds -*/ -extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); - -/*! @} */ - -/*! \defgroup pwm Pulse Width Modulation - Allows control of 2 independent PWM channels. A limited subset of GPIO pins - can be connected to one of these 2 channels, allowing PWM control of GPIO pins. - You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM - documentation on the Main Page. - @{ -*/ - -/*! Sets the PWM clock divisor, - to control the basic PWM pulse widths. - \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common - values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider -*/ -extern void bcm2835_pwm_set_clock(uint32_t divisor); - -/*! Sets the mode of the given PWM channel, - allowing you to control the PWM mode and enable/disable that channel - \param[in] channel The PWM channel. 0 or 1. - \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. - \param[in] enabled Set true to enable this channel and produce PWM pulses. -*/ -extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); - -/*! Sets the maximum range of the PWM output. - The data value can vary between 0 and this range to control PWM output - \param[in] channel The PWM channel. 0 or 1. - \param[in] range The maximum value permitted for DATA. -*/ -extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); - -/*! Sets the PWM pulse ratio to emit to DATA/RANGE, - where RANGE is set by bcm2835_pwm_set_range(). - \param[in] channel The PWM channel. 0 or 1. - \param[in] data Controls the PWM output ratio as a fraction of the range. - Can vary from 0 to RANGE. -*/ -extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); - -/*! @} */ -#ifdef __cplusplus -} -#endif - -#endif /* BCM2835_H */ - -/*! @example blink.c - Blinks RPi GPIO pin 11 on and off -*/ - -/*! @example input.c - Reads the state of an RPi input pin -*/ - -/*! @example event.c - Shows how to use event detection on an input pin -*/ - -/*! @example spi.c - Shows how to use SPI interface to transfer a byte to and from an SPI device -*/ - -/*! @example spin.c - Shows how to use SPI interface to transfer a number of bytes to and from an SPI device -*/ - -/*! @example pwm.c - Shows how to use PWM to control GPIO pins -*/ - -/*! @example i2c.c -Command line utility for executing i2c commands with the -Broadcom bcm2835. Contributed by Shahrooz Shahparnia. -*/ - -/*! example gpio.c - Command line utility for executing gpio commands with the - Broadcom bcm2835. Contributed by Shahrooz Shahparnia. -*/ - -/*! example spimem_test.c - Shows how to use the included little library (spiram.c and spiram.h) - to read and write SPI RAM chips such as 23K256-I/P -*/ diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/Arduino.h b/lib/MySensors/hal/architecture/Linux/drivers/core/Arduino.h deleted file mode 100644 index d683f9c7..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/Arduino.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef Arduino_h -#define Arduino_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "stdlib_noniso.h" - -#ifdef LINUX_ARCH_RASPBERRYPI -#include "RPi.h" -#define pinMode(pin, direction) RPi.pinMode(pin, direction) -#define digitalWrite(pin, value) RPi.digitalWrite(pin, value) -#define digitalRead(pin) RPi.digitalRead(pin) -#define digitalPinToInterrupt(pin) RPi.digitalPinToInterrupt(pin) -#else -#include "GPIO.h" -#define pinMode(pin, direction) GPIO.pinMode(pin, direction) -#define digitalWrite(pin, value) GPIO.digitalWrite(pin, value) -#define digitalRead(pin) GPIO.digitalRead(pin) -#define digitalPinToInterrupt(pin) GPIO.digitalPinToInterrupt(pin) -#endif - -#include "interrupt.h" - -#undef PSTR -#define PSTR(x) (x) -#undef F -#define F(x) (x) -#define PROGMEM __attribute__(( section(".progmem.data") )) -#define vsnprintf_P(...) vsnprintf( __VA_ARGS__ ) -#define snprintf_P(...) snprintf( __VA_ARGS__ ) -#define memcpy_P memcpy -#define pgm_read_byte(p) (*(p)) -#define pgm_read_dword(p) (*(p)) -#define pgm_read_byte_near(p) (*(p)) - -#define PI 3.1415926535897932384626433832795 -#define HALF_PI 1.5707963267948966192313216916398 -#define TWO_PI 6.283185307179586476925286766559 -#define DEG_TO_RAD 0.017453292519943295769236907684886 -#define RAD_TO_DEG 57.295779513082320876798154814105 -#define EULER 2.718281828459045235360287471352 - -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#define radians(deg) ((deg)*DEG_TO_RAD) -#define degrees(rad) ((rad)*RAD_TO_DEG) -#define sq(x) ((x)*(x)) -#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) - -#define lowByte(w) ((uint8_t) ((w) & 0xff)) -#define highByte(w) ((uint8_t) ((w) >> 8)) - -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) -#define bitSet(value, bit) ((value) |= (1UL << (bit))) -#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) - -#define bit(b) (1UL << (b)) - -#define GET_MACRO(_0, _1, _2, NAME, ...) NAME -#define random(...) GET_MACRO(_0, ##__VA_ARGS__, randMinMax, randMax, rand)(__VA_ARGS__) - -#ifndef delay -#define delay _delay_milliseconds -#endif - -#ifndef delayMicroseconds -#define delayMicroseconds _delay_microseconds -#endif - -using std::string; -using std::min; -using std::max; -using std::abs; - -typedef uint8_t byte; -typedef string String; -typedef char __FlashStringHelper; - -void yield(void); -unsigned long millis(void); -unsigned long micros(void); -void _delay_milliseconds(unsigned int millis); -void _delay_microseconds(unsigned int micro); -void randomSeed(unsigned long seed); -long randMax(long howbig); -long randMinMax(long howsmall, long howbig); - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/Client.h b/lib/MySensors/hal/architecture/Linux/drivers/core/Client.h deleted file mode 100644 index 6550f3d6..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/Client.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Client.h - Base class that provides Client - Copyright (c) 2011 Adrian McEwen. All right reserved. - - 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 - - Modified by Marcelo Aquino for MySensors use -*/ - -#ifndef client_h -#define client_h - -#include "Stream.h" -#include "IPAddress.h" - -#if !DOXYGEN -class Client : public Stream -{ - -public: - virtual int connect(IPAddress ip, uint16_t port) = 0; - virtual int connect(const char *host, uint16_t port) = 0; - virtual size_t write(uint8_t) = 0; - virtual size_t write(const uint8_t *buf, size_t size) = 0; - virtual int available() = 0; - virtual int read() = 0; - virtual int read(uint8_t *buf, size_t size) = 0; - virtual int peek() = 0; - virtual void flush() = 0; - virtual void stop() = 0; - virtual uint8_t connected() = 0; - virtual operator bool() = 0; - -protected: - uint8_t* rawIPAddress(IPAddress& addr) - { - return addr.raw_address(); - }; -}; -#endif - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetClient.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetClient.cpp deleted file mode 100644 index 41686b3c..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetClient.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on Arduino ethernet library, Copyright (c) 2010 Arduino LLC. All right reserved. - */ - -#include "EthernetClient.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "log.h" - -EthernetClient::EthernetClient() : _sock(-1) -{ -} - -EthernetClient::EthernetClient(int sock) : _sock(sock) -{ -} - -int EthernetClient::connect(const char* host, uint16_t port) -{ - struct addrinfo hints, *servinfo, *localinfo, *p; - int rv; - char s[INET6_ADDRSTRLEN]; - char port_str[6]; - bool use_bind = (_srcip != 0); - - close(); - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - sprintf(port_str, "%hu", port); - if ((rv = getaddrinfo(host, port_str, &hints, &servinfo)) != 0) { - logError("getaddrinfo: %s\n", gai_strerror(rv)); - return -1; - } - if (use_bind) { - if ((rv = getaddrinfo(_srcip.toString().c_str(), port_str, &hints, &localinfo)) != 0) { - logError("getaddrinfo: %s\n", gai_strerror(rv)); - return -1; - } - } - - // loop through all the results and connect to the first we can - for (p = servinfo; p != NULL; p = p->ai_next) { - if ((_sock = socket(p->ai_family, p->ai_socktype, - p->ai_protocol)) == -1) { - logError("socket: %s\n", strerror(errno)); - continue; - } - - if (use_bind) { - if (::bind(_sock, localinfo->ai_addr, localinfo->ai_addrlen) == -1) { - close(); - logError("bind: %s\n", strerror(errno)); - return -1; - } - } - - if (::connect(_sock, p->ai_addr, p->ai_addrlen) == -1) { - close(); - logError("connect: %s\n", strerror(errno)); - continue; - } - - break; - } - - if (p == NULL) { - logError("failed to connect\n"); - return -1; - } - - void *addr = &(((struct sockaddr_in*)p->ai_addr)->sin_addr); - inet_ntop(p->ai_family, addr, s, sizeof s); - logDebug("connected to %s\n", s); - - freeaddrinfo(servinfo); // all done with this structure - if (use_bind) { - freeaddrinfo(localinfo); // all done with this structure - } - - return 1; -} - -int EthernetClient::connect(IPAddress ip, uint16_t port) -{ - return connect(ip.toString().c_str(), port); -} - -size_t EthernetClient::write(uint8_t b) -{ - return write(&b, 1); -} - -size_t EthernetClient::write(const uint8_t *buf, size_t size) -{ - int bytes = 0; - - if (_sock == -1) { - return 0; - } - - while (size > 0) { - int rc = send(_sock, buf + bytes, size, MSG_NOSIGNAL | MSG_DONTWAIT); - if (rc == -1) { - logError("send: %s\n", strerror(errno)); - close(); - break; - } - bytes += rc; - size -= rc; - } - - return bytes; -} - -size_t EthernetClient::write(const char *str) -{ - if (str == NULL) { - return 0; - } - return write((const uint8_t *)str, strlen(str)); -} -size_t EthernetClient::write(const char *buffer, size_t size) -{ - return write((const uint8_t *)buffer, size); -} - -int EthernetClient::available() -{ - int count = 0; - - if (_sock != -1) { - ioctl(_sock, SIOCINQ, &count); - } - - return count; -} - -int EthernetClient::read() -{ - uint8_t b; - if ( recv(_sock, &b, 1, MSG_DONTWAIT) > 0 ) { - // recv worked - return b; - } else { - // No data available - return -1; - } -} - -int EthernetClient::read(uint8_t *buf, size_t bytes) -{ - return recv(_sock, buf, bytes, MSG_DONTWAIT); -} - -int EthernetClient::peek() -{ - uint8_t b; - - if (recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT) > 0) { - return b; - } else { - return -1; - } -} - -void EthernetClient::flush() -{ - int count = 0; - - if (_sock != -1) { - while (true) { - ioctl(_sock, SIOCOUTQ, &count); - if (count == 0) { - return; - } - usleep(1000); - } - } -} - -void EthernetClient::stop() -{ - if (_sock == -1) { - return; - } - - // attempt to close the connection gracefully (send a FIN to other side) - shutdown(_sock, SHUT_RDWR); - - timeval startTime, curTime; - gettimeofday(&startTime, NULL); - - // wait up to a second for the connection to close - do { - uint8_t s = status(); - if (s == ETHERNETCLIENT_W5100_CLOSED) { - break; // exit the loop - } - usleep(1000); - gettimeofday(&curTime, NULL); - } while (((curTime.tv_sec - startTime.tv_sec) * 1000000) + (curTime.tv_usec - startTime.tv_usec) < - 1000000); - - // free up the socket descriptor - ::close(_sock); - _sock = -1; -} - -uint8_t EthernetClient::status() -{ - if (_sock == -1) { - return ETHERNETCLIENT_W5100_CLOSED; - } - - struct tcp_info tcp_info; - int tcp_info_length = sizeof(tcp_info); - - if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info, - (socklen_t *)&tcp_info_length ) == 0 ) { - switch (tcp_info.tcpi_state) { - case TCP_ESTABLISHED: - return ETHERNETCLIENT_W5100_ESTABLISHED; - case TCP_SYN_SENT: - return ETHERNETCLIENT_W5100_SYNSENT; - case TCP_SYN_RECV: - return ETHERNETCLIENT_W5100_SYNRECV; - case TCP_FIN_WAIT1: - case TCP_FIN_WAIT2: - return ETHERNETCLIENT_W5100_FIN_WAIT; - case TCP_TIME_WAIT: - return TCP_TIME_WAIT; - case TCP_CLOSE: - return ETHERNETCLIENT_W5100_CLOSED; - case TCP_CLOSE_WAIT: - return ETHERNETCLIENT_W5100_CLOSING; - case TCP_LAST_ACK: - return ETHERNETCLIENT_W5100_LAST_ACK; - case TCP_LISTEN: - return ETHERNETCLIENT_W5100_LISTEN; - case TCP_CLOSING: - return ETHERNETCLIENT_W5100_CLOSING; - } - } - - return ETHERNETCLIENT_W5100_CLOSED; -} - -uint8_t EthernetClient::connected() -{ - return status() == ETHERNETCLIENT_W5100_ESTABLISHED || available(); -} - -void EthernetClient::close() -{ - if (_sock != -1) { - ::close(_sock); - _sock = -1; - } -} - -void EthernetClient::bind(IPAddress ip) -{ - _srcip = ip; -} - -int EthernetClient::getSocketNumber() -{ - return _sock; -} - -// the next function allows us to use the client returned by -// EthernetServer::available() as the condition in an if-statement. - -EthernetClient::operator bool() -{ - return _sock != -1; -} - -bool EthernetClient::operator==(const EthernetClient& rhs) -{ - return _sock == rhs._sock && _sock != -1 && rhs._sock != -1; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetClient.h b/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetClient.h deleted file mode 100644 index 5fac695e..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetClient.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on Arduino ethernet library, Copyright (c) 2010 Arduino LLC. All right reserved. - */ - -#ifndef EthernetClient_h -#define EthernetClient_h - -#include "Client.h" -#include "IPAddress.h" - -// State codes from W5100 library -#define ETHERNETCLIENT_W5100_CLOSED 0x00 -#define ETHERNETCLIENT_W5100_LISTEN 0x14 -#define ETHERNETCLIENT_W5100_SYNSENT 0x15 -#define ETHERNETCLIENT_W5100_SYNRECV 0x16 -#define ETHERNETCLIENT_W5100_ESTABLISHED 0x17 -#define ETHERNETCLIENT_W5100_FIN_WAIT 0x18 -#define ETHERNETCLIENT_W5100_CLOSING 0x1A -#define ETHERNETCLIENT_W5100_TIME_WAIT 0x1B -#define ETHERNETCLIENT_W5100_CLOSE_WAIT 0x1C -#define ETHERNETCLIENT_W5100_LAST_ACK 0x1D - -/** - * EthernetClient class - */ -class EthernetClient : public Client -{ - -public: - /** - * @brief EthernetClient constructor. - */ - EthernetClient(); - /** - * @brief EthernetClient constructor. - * - * @param sock Network socket. - */ - explicit EthernetClient(int sock); - /** - * @brief Initiate a connection with host:port. - * - * @param host name to resolve or a stringified dotted IP address. - * @param port to connect to. - * @return 1 if SUCCESS or -1 if FAILURE. - */ - virtual int connect(const char *host, uint16_t port); - /** - * @brief Initiate a connection with ip:port. - * - * @param ip to connect to. - * @param port to connect to. - * @return 1 if SUCCESS or -1 if FAILURE. - */ - virtual int connect(IPAddress ip, uint16_t port); - /** - * @brief Write a byte. - * - * @param b byte to write. - * @return 0 if FAILURE or 1 if SUCCESS. - */ - virtual size_t write(uint8_t b); - /** - * @brief Write at most 'size' bytes. - * - * @param buf Buffer to read from. - * @param size of the buffer. - * @return 0 if FAILURE or the number of bytes sent. - */ - virtual size_t write(const uint8_t *buf, size_t size); - /** - * @brief Write a null-terminated string. - * - * @param str String to write. - * @return 0 if FAILURE or number of characters sent. - */ - size_t write(const char *str); - /** - * @brief Write at most 'size' characters. - * - * @param buffer to read from. - * @param size of the buffer. - * @return 0 if FAILURE or the number of characters sent. - */ - size_t write(const char *buffer, size_t size); - /** - * @brief Returns the number of bytes available for reading. - * - * @return number of bytes available. - */ - virtual int available(); - /** - * @brief Read a byte. - * - * @return -1 if no data, else the first byte available. - */ - virtual int read(); - /** - * @brief Read a number of bytes and store in a buffer. - * - * @param buf buffer to write to. - * @param bytes number of bytes to read. - * @return -1 if no data or number of read bytes. - */ - virtual int read(uint8_t *buf, size_t bytes); - /** - * @brief Returns the next byte of the read queue without removing it from the queue. - * - * @return -1 if no data, else the first byte of incoming data available. - */ - virtual int peek(); - /** - * @brief Waits until all outgoing bytes in buffer have been sent. - */ - virtual void flush(); - /** - * @brief Close the connection gracefully. - * - * Send a FIN and wait 1s for a response. If no response close it forcefully. - */ - virtual void stop(); - /** - * @brief Connection status. - * - * @return state according to W5100 library codes. - */ - uint8_t status(); - /** - * @brief Whether or not the client is connected. - * - * Note that a client is considered connected if the connection has been closed but - * there is still unread data. - * - * @return 1 if the client is connected, 0 if not. - */ - virtual uint8_t connected(); - /** - * @brief Close the connection. - */ - void close(); - /** - * @brief Bind the conection to the specified local ip. - */ - void bind(IPAddress ip); - /** - * @brief Get the internal socket file descriptor. - * - * @return an integer, that is the socket number. - */ - int getSocketNumber(); - /** - * @brief Overloaded cast operators. - * - * Allow EthernetClient objects to be used where a bool is expected. - */ - virtual operator bool(); - /** - * @brief Overloaded cast operators. - * - */ - virtual bool operator==(const bool value) - { - return bool() == value; - } - /** - * @brief Overloaded cast operators. - * - */ - virtual bool operator!=(const bool value) - { - return bool() != value; - } - /** - * @brief Overloaded cast operators. - * - */ - virtual bool operator==(const EthernetClient& rhs); - /** - * @brief Overloaded cast operators. - * - */ - virtual bool operator!=(const EthernetClient& rhs) - { - return !this->operator==(rhs); - }; - - friend class EthernetServer; - -private: - int _sock; //!< @brief Network socket file descriptor. - IPAddress _srcip; //!< @brief Local ip to bind to. -}; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetServer.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetServer.cpp deleted file mode 100644 index b2149332..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetServer.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on Arduino ethernet library, Copyright (c) 2010 Arduino LLC. All right reserved. - */ - -#include "EthernetServer.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "log.h" -#include "EthernetClient.h" - -EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port), - max_clients(max_clients), sockfd(-1) -{ - clients.reserve(max_clients); -} - -void EthernetServer::begin() -{ - begin(IPAddress(0,0,0,0)); -} - -void EthernetServer::begin(IPAddress address) -{ - struct addrinfo hints, *servinfo, *p; - int yes=1; - int rv; - char ipstr[INET_ADDRSTRLEN]; - char portstr[6]; - - if (sockfd != -1) { - close(sockfd); - sockfd = -1; - } - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - - sprintf(portstr, "%d", port); - if ((rv = getaddrinfo(address.toString().c_str(), portstr, &hints, &servinfo)) != 0) { - logError("getaddrinfo: %s\n", gai_strerror(rv)); - return; - } - - // loop through all the results and bind to the first we can - for (p = servinfo; p != NULL; p = p->ai_next) { - if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { - logError("socket: %s\n", strerror(errno)); - continue; - } - - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { - logError("setsockopt: %s\n", strerror(errno)); - freeaddrinfo(servinfo); - return; - } - - if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { - close(sockfd); - logError("bind: %s\n", strerror(errno)); - continue; - } - - break; - } - - if (p == NULL) { - logError("Failed to bind!\n"); - freeaddrinfo(servinfo); - return; - } - - if (listen(sockfd, ETHERNETSERVER_BACKLOG) == -1) { - logError("listen: %s\n", strerror(errno)); - freeaddrinfo(servinfo); - return; - } - - freeaddrinfo(servinfo); - - fcntl(sockfd, F_SETFL, O_NONBLOCK); - - struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; - void *addr = &(ipv4->sin_addr); - inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); - logDebug("Listening for connections on %s:%s\n", ipstr, portstr); -} - -bool EthernetServer::hasClient() -{ - // Check if any client has disconnected - for (size_t i = 0; i < clients.size(); ++i) { - EthernetClient client(clients[i]); - if (!client.connected()) { - // Checks if this disconnected client is also on the new clients list - for (std::list::iterator it = new_clients.begin(); it != new_clients.end(); ++it) { - if (*it == clients[i]) { - new_clients.erase(it); - break; - } - } - client.stop(); - clients[i] = clients.back(); - clients.pop_back(); - logDebug("Ethernet client disconnected.\n"); - } - } - - _accept(); - - return !new_clients.empty(); -} - -EthernetClient EthernetServer::available() -{ - if (new_clients.empty()) { - return EthernetClient(); - } else { - int sock = new_clients.front(); - new_clients.pop_front(); - return EthernetClient(sock); - } -} - -size_t EthernetServer::write(uint8_t b) -{ - return write(&b, 1); -} - -size_t EthernetServer::write(const uint8_t *buffer, size_t size) -{ - size_t n = 0; - - for (size_t i = 0; i < clients.size(); ++i) { - EthernetClient client(clients[i]); - if (client.status() == ETHERNETCLIENT_W5100_ESTABLISHED) { - n += client.write(buffer, size); - } - } - - return n; -} - -size_t EthernetServer::write(const char *str) -{ - if (str == NULL) { - return 0; - } - return write((const uint8_t *)str, strlen(str)); -} - -size_t EthernetServer::write(const char *buffer, size_t size) -{ - return write((const uint8_t *)buffer, size); -} - -void EthernetServer::_accept() -{ - int new_fd; - socklen_t sin_size; - struct sockaddr_storage client_addr; - char ipstr[INET_ADDRSTRLEN]; - - sin_size = sizeof client_addr; - new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size); - if (new_fd == -1) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - logError("accept: %s\n", strerror(errno)); - } - return; - } - - if (clients.size() == max_clients) { - // no free slots, search for a dead client - close(new_fd); - logDebug("Max number of ethernet clients reached.\n"); - return; - } - - new_clients.push_back(new_fd); - clients.push_back(new_fd); - - void *addr = &(((struct sockaddr_in*)&client_addr)->sin_addr); - inet_ntop(client_addr.ss_family, addr, ipstr, sizeof ipstr); - logDebug("New connection from %s\n", ipstr); -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetServer.h b/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetServer.h deleted file mode 100644 index d0f03aef..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/EthernetServer.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on Arduino ethernet library, Copyright (c) 2010 Arduino LLC. All right reserved. - */ - -#ifndef EthernetServer_h -#define EthernetServer_h - -#include -#include -#include "Server.h" -#include "IPAddress.h" - -#ifdef ETHERNETSERVER_MAX_CLIENTS -#define ETHERNETSERVER_BACKLOG ETHERNETSERVER_MAX_CLIENTS //!< Maximum length to which the queue of pending connections may grow. -#else -#define ETHERNETSERVER_MAX_CLIENTS 10 //!< Default value for max_clients. -#define ETHERNETSERVER_BACKLOG 10 //!< Maximum length to which the queue of pending connections may grow. -#endif - -class EthernetClient; - -/** - * @brief EthernetServer class - */ -class EthernetServer : public Server -{ - -public: - /** - * @brief EthernetServer constructor. - * - * @param port number for the socket addresses. - * @param max_clients The maximum number allowed for connected clients. - */ - EthernetServer(uint16_t port, uint16_t max_clients = ETHERNETSERVER_MAX_CLIENTS); - /** - * @brief Listen for inbound connection request. - * - */ - virtual void begin(); - /** - * @brief Listen on the specified ip for inbound connection request. - * - * @param addr IP address to bind to. - */ - void begin(IPAddress addr); - /** - * @brief Verifies if a new client has connected. - * - * @return @c true if a new client has connected, else @c false. - */ - bool hasClient(); - /** - * @brief Get the new connected client. - * - * @return a EthernetClient object; if no new client has connected, this object will evaluate to false. - */ - EthernetClient available(); - /** - * @brief Write a byte to all clients. - * - * @param b byte to send. - * @return 0 if FAILURE or 1 if SUCCESS. - */ - virtual size_t write(uint8_t b); - /** - * @brief Write at most 'size' bytes to all clients. - * - * @param buffer to read from. - * @param size of the buffer. - * @return 0 if FAILURE else number of bytes sent. - */ - virtual size_t write(const uint8_t *buffer, size_t size); - /** - * @brief Write a null-terminated string to all clients. - * - * @param str String to write. - * @return 0 if FAILURE else number of characters sent. - */ - size_t write(const char *str); - /** - * @brief Write at most 'size' characters to all clients. - * - * @param buffer to read from. - * @param size of the buffer. - * @return 0 if FAILURE else the number of characters sent. - */ - size_t write(const char *buffer, size_t size); - -private: - uint16_t port; //!< @brief Port number for the network socket. - std::list new_clients; //!< Socket list of new connected clients. - std::vector clients; //!< @brief Socket list of connected clients. - uint16_t max_clients; //!< @brief The maximum number of allowed clients. - int sockfd; //!< @brief Network socket used to accept connections. - - /** - * @brief Accept new clients if the total of connected clients is below max_clients. - * - */ - void _accept(); -}; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/GPIO.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/GPIO.cpp deleted file mode 100644 index 62e4ef58..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/GPIO.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "GPIO.h" -#include -#include -#include -#include -#include -#include -#include "log.h" - -// Declare a single default instance -GPIOClass GPIO = GPIOClass(); - -GPIOClass::GPIOClass() -{ - FILE *f; - DIR* dp; - char file[64]; - - dp = opendir("/sys/class/gpio"); - if (dp == NULL) { - logError("Could not open /sys/class/gpio directory"); - exit(1); - } - - lastPinNum = 0; - - while (true) { - dirent *de = readdir(dp); - if (de == NULL) { - break; - } - - if (strncmp("gpiochip", de->d_name, 8) == 0) { - snprintf(file, sizeof(file), "/sys/class/gpio/%s/base", de->d_name); - f = fopen(file, "r"); - int base; - if (fscanf(f, "%d", &base) == EOF) { - logError("Failed to open %s\n", file); - base = 0; - } - fclose(f); - - snprintf(file, sizeof(file), "/sys/class/gpio/%s/ngpio", de->d_name); - f = fopen(file, "r"); - int ngpio; - if (fscanf(f, "%d", &ngpio) == EOF) { - logError("Failed to open %s\n", file); - ngpio = 0; - } - fclose(f); - - int max = ngpio + base - 1; - if (lastPinNum < max) { - lastPinNum = max; - } - } - } - closedir(dp); - - exportedPins = new uint8_t[lastPinNum + 1]; - - for (int i = 0; i < lastPinNum + 1; ++i) { - exportedPins[i] = 0; - } -} - -GPIOClass::GPIOClass(const GPIOClass& other) -{ - lastPinNum = other.lastPinNum; - - exportedPins = new uint8_t[lastPinNum + 1]; - for (int i = 0; i < lastPinNum + 1; ++i) { - exportedPins[i] = other.exportedPins[i]; - } -} - -GPIOClass::~GPIOClass() -{ - FILE *f; - - for (int i = 0; i < lastPinNum + 1; ++i) { - if (exportedPins[i]) { - f = fopen("/sys/class/gpio/unexport", "w"); - fprintf(f, "%d\n", i); - fclose(f); - } - } - - delete [] exportedPins; -} - -void GPIOClass::pinMode(uint8_t pin, uint8_t mode) -{ - FILE *f; - - if (pin > lastPinNum) { - return; - } - - f = fopen("/sys/class/gpio/export", "w"); - fprintf(f, "%d\n", pin); - fclose(f); - - int counter = 0; - char file[128]; - sprintf(file, "/sys/class/gpio/gpio%d/direction", pin); - - while ((f = fopen(file,"w")) == NULL) { - // Wait 10 seconds for the file to be accessible if not open on first attempt - sleep(1); - counter++; - if (counter > 10) { - logError("Could not open /sys/class/gpio/gpio%u/direction", pin); - exit(1); - } - } - if (mode == INPUT) { - fprintf(f, "in\n"); - } else { - fprintf(f, "out\n"); - } - - exportedPins[pin] = 1; - - fclose(f); -} - -void GPIOClass::digitalWrite(uint8_t pin, uint8_t value) -{ - FILE *f; - char file[128]; - - if (pin > lastPinNum) { - return; - } - if (0 == exportedPins[pin]) { - pinMode(pin, OUTPUT); - } - - sprintf(file, "/sys/class/gpio/gpio%d/value", pin); - f = fopen(file, "w"); - - if (value == 0) { - fprintf(f, "0\n"); - } else { - fprintf(f, "1\n"); - } - - fclose(f); -} - -uint8_t GPIOClass::digitalRead(uint8_t pin) -{ - FILE *f; - char file[128]; - - if (pin > lastPinNum) { - return 0; - } - if (0 == exportedPins[pin]) { - pinMode(pin, INPUT); - } - - sprintf(file, "/sys/class/gpio/gpio%d/value", pin); - f = fopen(file, "r"); - - int i; - if (fscanf(f, "%d", &i) == EOF) { - logError("digitalRead: failed to read pin %u\n", pin); - i = 0; - } - fclose(f); - return i; -} - -uint8_t GPIOClass::digitalPinToInterrupt(uint8_t pin) -{ - return pin; -} - -GPIOClass& GPIOClass::operator=(const GPIOClass& other) -{ - if (this != &other) { - lastPinNum = other.lastPinNum; - - exportedPins = new uint8_t[lastPinNum + 1]; - for (int i = 0; i < lastPinNum + 1; ++i) { - exportedPins[i] = other.exportedPins[i]; - } - } - return *this; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/GPIO.h b/lib/MySensors/hal/architecture/Linux/drivers/core/GPIO.h deleted file mode 100644 index 48ecabd1..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/GPIO.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef GPIO_h -#define GPIO_h - -#include - -#define INPUT 0 -#define OUTPUT 1 - -#define LOW 0 -#define HIGH 1 - -/** - * @brief GPIO class - */ -class GPIOClass -{ - -public: - /** - * @brief GPIOClass constructor. - */ - GPIOClass(); - /** - * @brief GPIOClass copy constructor. - */ - GPIOClass(const GPIOClass& other); - /** - * @brief GPIOClass destructor. - */ - ~GPIOClass(); - /** - * @brief Configures the specified pin to behave either as an input or an output. - * - * @param pin The number of the pin. - * @param mode INPUT or OUTPUT. - */ - void pinMode(uint8_t pin, uint8_t mode); - /** - * @brief Write a high or a low value for the given pin. - * - * @param pin number. - * @param value HIGH or LOW. - */ - void digitalWrite(uint8_t pin, uint8_t value); - /** - * @brief Reads the value from a specified pin. - * - * @param pin The number of the pin. - * @return HIGH or LOW. - */ - uint8_t digitalRead(uint8_t pin); - /** - * @brief Arduino compatibility function, returns the same given pin. - * - * @param pin The number of the pin. - * @return The same parameter pin number. - */ - uint8_t digitalPinToInterrupt(uint8_t pin); - /** - * @brief Overloaded assign operator. - * - */ - GPIOClass& operator=(const GPIOClass& other); - -private: - int lastPinNum; //!< @brief Highest pin number supported. - uint8_t *exportedPins; //!< @brief Array with information of which pins were exported. -}; - -extern GPIOClass GPIO; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/IPAddress.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/IPAddress.cpp deleted file mode 100644 index 963f7e29..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/IPAddress.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * IPAddress.cpp - Base class that provides IPAddress - * Copyright (c) 2011 Adrian McEwen. All right reserved. - * - * 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 - * - * - * Modified by Marcelo Aquino for MySensors use - */ - -#include -#include -#include "IPAddress.h" - -IPAddress::IPAddress() -{ - _address.dword = 0; -} - -IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, - uint8_t fourth_octet) -{ - _address.bytes[0] = first_octet; - _address.bytes[1] = second_octet; - _address.bytes[2] = third_octet; - _address.bytes[3] = fourth_octet; -} - -IPAddress::IPAddress(uint32_t address) -{ - _address.dword = address; -} - -IPAddress::IPAddress(const uint8_t *address) -{ - memcpy(_address.bytes, address, sizeof(_address.bytes)); -} - -bool IPAddress::fromString(const char *address) -{ - // TODO: add support for "a", "a.b", "a.b.c" formats - - uint16_t acc = 0; // Accumulator - uint8_t dots = 0; - - while (*address) { - char c = *address++; - if (c >= '0' && c <= '9') { - acc = acc * 10 + (c - '0'); - if (acc > 255) { - // Value out of [0..255] range - return false; - } - } else if (c == '.') { - if (dots == 3) { - // Too much dots (there must be 3 dots) - return false; - } - _address.bytes[dots++] = acc; - acc = 0; - } else { - // Invalid char - return false; - } - } - - if (dots != 3) { - // Too few dots (there must be 3 dots) - return false; - } - _address.bytes[3] = acc; - return true; -} - -IPAddress& IPAddress::operator=(const uint8_t *address) -{ - memcpy(_address.bytes, address, sizeof(_address.bytes)); - return *this; -} - -IPAddress& IPAddress::operator=(uint32_t address) -{ - _address.dword = address; - return *this; -} - -bool IPAddress::operator==(const uint8_t* addr) const -{ - return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; -} - -std::string IPAddress::toString() -{ - char szRet[16]; - sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], - _address.bytes[3]); - return std::string(szRet); -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/IPAddress.h b/lib/MySensors/hal/architecture/Linux/drivers/core/IPAddress.h deleted file mode 100644 index 43e131e4..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/IPAddress.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * IPAddress.h - Base class that provides IPAddress - * Copyright (c) 2011 Adrian McEwen. All right reserved. - * - * 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 - * - * - * Modified by Marcelo Aquino for MySensors use - */ - -#ifndef IPAddress_h -#define IPAddress_h - -#include -#include - -/** - * @brief A class to make it easier to handle and pass around IP addresses - */ -class IPAddress -{ -private: - union { - uint8_t bytes[4]; //!< IPv4 address as an array - uint32_t dword; //!< IPv4 address in 32 bits format - } _address; - - /** - * @brief Access the raw byte array containing the address. - * - * Because this returns a pointer to the internal structure rather than a copy of the address - * this function should only be used when you know that the usage of the returned uint8_t* will - * be transient and not stored. - * - * @return pointer to the internal structure. - */ - uint8_t* raw_address() - { - return _address.bytes; - } - -public: - /** - * @brief IPAddress constructor. - */ - IPAddress(); - /** - * @brief IPAddress constructor. - * - * @param first_octet first octet of the IPv4 address. - * @param second_octet second octet of the IPv4 address. - * @param third_octet third octet of the IPv4 address. - * @param fourth_octet fourth octet of the IPv4 address. - */ - IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); - /** - * @brief IPAddress constructor. - * - * @param address to be set from a 32 bits integer. - */ - explicit IPAddress(uint32_t address); - /** - * @brief IPAddress constructor. - * - * @param address to be set from a byte array. - */ - explicit IPAddress(const uint8_t *address); - /** - * @brief Set the IP from a array of characters. - * - * @param address to be set. - */ - bool fromString(const char *address); - /** - * @brief Set the IP from a string class type. - * - * @param address to be set. - */ - bool fromString(const std::string &address) - { - return fromString(address.c_str()); - } - /** - * @brief Overloaded cast operator - * - * Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected - */ - operator uint32_t() const - { - return _address.dword; - } - /** - * @brief Overloaded cast operator - * - */ - bool operator==(const IPAddress& addr) const - { - return _address.dword == addr._address.dword; - } - /** - * @brief Overloaded cast operator - * - */ - bool operator==(uint32_t addr) const - { - return _address.dword == addr; - } - /** - * @brief Overloaded cast operator - * - */ - bool operator==(const uint8_t* addr) const; - /** - * @brief Overloaded index operator. - * - * Allow getting and setting individual octets of the address. - * - */ - uint8_t operator[](int index) const - { - return _address.bytes[index]; - } - /** - * @brief Overloaded index operator - * - */ - uint8_t& operator[](int index) - { - return _address.bytes[index]; - } - /** - * @brief Overloaded copy operators. - * - * Allow initialisation of IPAddress objects from byte array. - */ - IPAddress& operator=(const uint8_t *address); - /** - * @brief Overloaded copy operator. - * - * Allow initialisation of IPAddress objects from a 32 bits integer. - */ - IPAddress& operator=(uint32_t address); - /** - * @brief Convert the IP address to a string. - * - * @return A stringified IP address - */ - std::string toString(); - - friend class Client; -}; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/Print.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/Print.cpp deleted file mode 100644 index a915e33f..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/Print.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* - Print.cpp - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. All right reserved. - - 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 - - Modified 23 November 2006 by David A. Mellis - Modified December 2014 by Ivan Grokhotkov - Modified May 2015 by Michael C. Miller - esp8266 progmem support - Modified August 2016 by Marcelo Aquino for MySensors use - */ - -#include -#include -#include -#include -#include "Print.h" - -// Public Methods ////////////////////////////////////////////////////////////// - -size_t Print::write(const uint8_t *buffer, size_t size) -{ - size_t n = 0; - while(size--) { - n += write(*buffer++); - } - return n; -} - -size_t -#ifdef __GNUC__ -__attribute__((format(printf, 2, 3))) -#endif -Print::printf(const char *format, ...) -{ - va_list arg; - va_start(arg, format); - char temp[64]; - char* buffer = temp; - size_t len = vsnprintf(temp, sizeof(temp), format, arg); - va_end(arg); - if (len > sizeof(temp) - 1) { - buffer = new char[len + 1]; - if (!buffer) { - return 0; - } - va_start(arg, format); - vsnprintf(buffer, len + 1, format, arg); - va_end(arg); - } - len = write((const uint8_t*) buffer, len); - if (buffer != temp) { - delete[] buffer; - } - return len; -} - -size_t Print::print(const std::string &s) -{ - return write(s.c_str(), s.length()); -} - -size_t Print::print(const char str[]) -{ - return write(str); -} - -size_t Print::print(char c) -{ - return write(c); -} - -size_t Print::print(unsigned char b, int base) -{ - return print((unsigned long) b, base); -} - -size_t Print::print(int n, int base) -{ - return print((long) n, base); -} - -size_t Print::print(unsigned int n, int base) -{ - return print((unsigned long) n, base); -} - -size_t Print::print(long n, int base) -{ - if(base == 0) { - return write(n); - } else if(base == 10) { - if(n < 0) { - int t = print('-'); - n = -n; - return printNumber(n, 10) + t; - } - return printNumber(n, 10); - } else { - return printNumber(n, base); - } -} - -size_t Print::print(unsigned long n, int base) -{ - if(base == 0) { - return write(n); - } else { - return printNumber(n, base); - } -} - -size_t Print::print(double n, int digits) -{ - return printFloat(n, digits); -} - -size_t Print::println(void) -{ - return print("\r\n"); -} - -size_t Print::println(const std::string &s) -{ - size_t n = print(s); - n += println(); - return n; -} - -size_t Print::println(const char c[]) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(char c) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(unsigned char b, int base) -{ - size_t n = print(b, base); - n += println(); - return n; -} - -size_t Print::println(int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(double num, int digits) -{ - size_t n = print(num, digits); - n += println(); - return n; -} - -// Private Methods ///////////////////////////////////////////////////////////// - -size_t Print::printNumber(unsigned long n, uint8_t base) -{ - char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. - char *str = &buf[sizeof(buf) - 1]; - - *str = '\0'; - - // prevent crash if called with base == 1 - if(base < 2) { - base = 10; - } - - do { - char c = n % base; - n /= base; - - *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); - - return write(str); -} - -size_t Print::printFloat(double number, uint8_t digits) -{ - size_t n = 0; - - if(std::isnan(number)) { - return print("nan"); - } - if(std::isinf(number)) { - return print("inf"); - } - if(number > 4294967040.0) { - return print("ovf"); // constant determined empirically - } - if(number < -4294967040.0) { - return print("ovf"); // constant determined empirically - } - - // Handle negative numbers - if(number < 0.0) { - n += print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - for(uint8_t i = 0; i < digits; ++i) { - rounding /= 10.0; - } - - number += rounding; - - // Extract the integer part of the number and print it - unsigned long int_part = (unsigned long) number; - double remainder = number - (double) int_part; - n += print(int_part); - - // Print the decimal point, but only if there are digits beyond - if(digits > 0) { - n += print("."); - } - - // Extract digits from the remainder one at a time - while(digits-- > 0) { - remainder *= 10.0; - int toPrint = int(remainder); - n += print(toPrint); - remainder -= toPrint; - } - - return n; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/Print.h b/lib/MySensors/hal/architecture/Linux/drivers/core/Print.h deleted file mode 100644 index ff8f6953..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/Print.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - Print.h - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. All right reserved. - - 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 - - Modified August 2016 by Marcelo Aquino for MySensors use - */ - -#ifndef Print_h -#define Print_h - -#include -#include -#include - -#if !DOXYGEN -#define DEC 10 -#define HEX 16 -#define OCT 8 -#define BIN 2 - -class Print -{ -private: - int write_error; - size_t printNumber(unsigned long n, uint8_t base); - size_t printFloat(double number, uint8_t digits); - -protected: - void setWriteError(int err = 1) - { - write_error = err; - } - -public: - Print() : write_error(0) {} - - int getWriteError() - { - return write_error; - } - void clearWriteError() - { - setWriteError(0); - } - - virtual size_t write(uint8_t) = 0; - size_t write(const char *str) - { - if (str == NULL) { - return 0; - } - return write((const uint8_t *) str, strlen(str)); - } - virtual size_t write(const uint8_t *buffer, size_t size); - size_t write(const char *buffer, size_t size) - { - return write((const uint8_t *) buffer, size); - } - - size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3))); - size_t print(const std::string &); - size_t print(const char[]); - size_t print(char); - size_t print(unsigned char, int = DEC); - size_t print(int, int = DEC); - size_t print(unsigned int, int = DEC); - size_t print(long, int = DEC); - size_t print(unsigned long, int = DEC); - size_t print(double, int = 2); - - size_t println(const std::string &s); - size_t println(const char[]); - size_t println(char); - size_t println(unsigned char, int = DEC); - size_t println(int, int = DEC); - size_t println(unsigned int, int = DEC); - size_t println(long, int = DEC); - size_t println(unsigned long, int = DEC); - size_t println(double, int = 2); - size_t println(void); -}; - -#endif -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/SPI.h b/lib/MySensors/hal/architecture/Linux/drivers/core/SPI.h deleted file mode 100644 index 972484f6..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/SPI.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef _SPI_H_ -#define _SPI_H_ - -#ifdef LINUX_SPI_BCM -#include "SPIBCM.h" -#define SPI SPIBCM -#elif LINUX_SPI_SPIDEV -#include "SPIDEV.h" -#define SPI SPIDEV -#endif - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/SPIDEV.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/SPIDEV.cpp deleted file mode 100644 index 06179284..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/SPIDEV.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on TMRh20 RF24 library, Copyright (c) 2015 Charles-Henri Hallard - */ - -#include "SPIDEV.h" -#include -#include -#include -#include -#include -#include -#include "log.h" - -static pthread_mutex_t spiMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutexattr_t attr; - -// Declare a single default instance -SPIDEVClass SPIDEV = SPIDEVClass(); - -uint8_t SPIDEVClass::initialized = 0; -int SPIDEVClass::fd = -1; -std::string SPIDEVClass::device = SPI_SPIDEV_DEVICE; -uint8_t SPIDEVClass::mode = SPI_MODE0; -uint32_t SPIDEVClass::speed = SPI_CLOCK_BASE; -uint8_t SPIDEVClass::bit_order = MSBFIRST; -struct spi_ioc_transfer SPIDEVClass::tr = {0,0,0,0,0,8,0,0,0,0}; // 8 bits_per_word, 0 cs_change - -SPIDEVClass::SPIDEVClass() -{ - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&spiMutex, &attr); -} - -void SPIDEVClass::begin(int busNo) -{ - if (!initialized) { - /* set spidev accordingly to busNo like: - * busNo = 23 -> /dev/spidev2.3 - * - * a bit messy but simple - * */ - device[11] += (busNo / 10) % 10; - device[13] += busNo % 10; - - init(); - } - - initialized++; // reference count -} - -void SPIDEVClass::end() -{ - if (initialized) { - initialized--; - } - - if (!initialized) { - if (!(fd < 0)) { - close(fd); - fd = -1; - } - } -} - -void SPIDEVClass::setBitOrder(uint8_t border) -{ - pthread_mutex_lock(&spiMutex); - - /* - * bit order - */ - bit_order = border; - int ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order); - if (ret == -1) { - logError("Can't set SPI bit order.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order); - if (ret == -1) { - logError("Can't set SPI bit order.\n"); - abort(); - } - - pthread_mutex_unlock(&spiMutex); -} - -void SPIDEVClass::setDataMode(uint8_t data_mode) -{ - pthread_mutex_lock(&spiMutex); - - /* - * spi mode - */ - mode = data_mode; - int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); - if (ret == -1) { - logError("Can't set SPI mode.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); - if (ret == -1) { - logError("Can't set SPI mode.\n"); - abort(); - } - - pthread_mutex_unlock(&spiMutex); -} - -void SPIDEVClass::setClockDivider(uint16_t divider) -{ - if (divider == 0) { - return; - } - - pthread_mutex_lock(&spiMutex); - - /* - * max speed hz - */ - speed = SPI_CLOCK_BASE / divider; - int ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); - if (ret == -1) { - logError("Can't set SPI max speed hz.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); - if (ret == -1) { - logError("Can't set SPI max speed hz.\n"); - abort(); - } - - pthread_mutex_unlock(&spiMutex); -} - -void SPIDEVClass::chipSelect(int csn_chip) -{ - if (csn_chip >= 0 && csn_chip <= 9) { - device[13] = '0' + (csn_chip % 10); - - init(); - } -} - -uint8_t SPIDEVClass::transfer(uint8_t data) -{ - int ret; - uint8_t tx[1] = {data}; - uint8_t rx[1] = {0}; - - pthread_mutex_lock(&spiMutex); - - tr.tx_buf = (unsigned long)&tx[0]; - tr.rx_buf = (unsigned long)&rx[0]; - tr.len = 1; - tr.speed_hz = speed; - - ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); - if (ret < 1) { - logError("Can't send spi message.\n"); - abort(); - } - - pthread_mutex_unlock(&spiMutex); - - return rx[0]; -} - -void SPIDEVClass::transfernb(char* tbuf, char* rbuf, uint32_t len) -{ - int ret; - - pthread_mutex_lock(&spiMutex); - - tr.tx_buf = (unsigned long)tbuf; - tr.rx_buf = (unsigned long)rbuf; - tr.len = len; - tr.speed_hz = speed; - - ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); - if (ret < 1) { - logError("Can't send spi message.\n"); - abort(); - } - - pthread_mutex_unlock(&spiMutex); -} - -void SPIDEVClass::transfern(char* buf, uint32_t len) -{ - transfernb(buf, buf, len); -} - -void SPIDEVClass::beginTransaction(SPISettings settings) -{ - int ret; - - pthread_mutex_lock(&spiMutex); - - /* - * spi mode - */ - if (settings.dmode != mode) { - mode = settings.dmode; - - ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); - if (ret == -1) { - logError("Can't set spi mode.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); - if (ret == -1) { - logError("Can't set spi mode.\n"); - abort(); - } - } - - /* - * speed - */ - if (settings.clock != speed) { - speed = settings.clock; - - ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); - if (ret == -1) { - logError("Can't set SPI max speed hz.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); - if (ret == -1) { - logError("Can't set SPI max speed hz.\n"); - abort(); - } - } - - /* - * bit order - */ - if (settings.border != bit_order) { - bit_order = settings.border; - - ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order); - if (ret == -1) { - logError("Can't set SPI bit order.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order); - if (ret == -1) { - logError("Can't set SPI bit order.\n"); - abort(); - } - } -} - -void SPIDEVClass::endTransaction() -{ - pthread_mutex_unlock(&spiMutex); -} - -void SPIDEVClass::usingInterrupt(uint8_t interruptNumber) -{ - (void)interruptNumber; -} - -void SPIDEVClass::notUsingInterrupt(uint8_t interruptNumber) -{ - (void)interruptNumber; -} - -void SPIDEVClass::init() -{ - pthread_mutex_lock(&spiMutex); - - if (fd >= 0) { - close(fd); - } - - fd = open(device.c_str(), O_RDWR); - if (fd < 0) { - logError("Can't open SPI device: %s\n", device.c_str()); - abort(); - } - - /* - * spi mode - */ - int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); - if (ret == -1) { - logError("Can't set SPI mode.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); - if (ret == -1) { - logError("Can't set SPI mode.\n"); - abort(); - } - - /* - * bits per word - */ - uint8_t bits = 8; // 8 bits per word - ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); - if (ret == -1) { - logError("Can't set SPI bits per word.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); - if (ret == -1) { - logError("Can't set SPI bits per word.\n"); - abort(); - } - - /* - * max speed hz - */ - ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); - if (ret == -1) { - logError("Can't set SPI max speed hz.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); - if (ret == -1) { - logError("Can't set SPI max speed hz.\n"); - abort(); - } - - /* - * bit order - */ - ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order); - if (ret == -1) { - logError("Can't set SPI bit order.\n"); - abort(); - } - - ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order); - if (ret == -1) { - logError("Can't set SPI bit order.\n"); - abort(); - } - - pthread_mutex_unlock(&spiMutex); -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/SPIDEV.h b/lib/MySensors/hal/architecture/Linux/drivers/core/SPIDEV.h deleted file mode 100644 index 29110c2a..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/SPIDEV.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on TMRh20 RF24 library, Copyright (c) 2015 Charles-Henri Hallard - */ - -#ifndef SPIDEV_h -#define SPIDEV_h - -#include -#include -#include - -#define SPI_HAS_TRANSACTION - -#define MSBFIRST 0 -#define LSBFIRST SPI_LSB_FIRST - -#define SPI_CLOCK_BASE 16000000 // 16Mhz - -#define SPI_CLOCK_DIV1 1 -#define SPI_CLOCK_DIV2 2 -#define SPI_CLOCK_DIV4 4 -#define SPI_CLOCK_DIV8 8 -#define SPI_CLOCK_DIV16 16 -#define SPI_CLOCK_DIV32 32 -#define SPI_CLOCK_DIV64 64 -#define SPI_CLOCK_DIV128 128 -#define SPI_CLOCK_DIV256 256 - -// SPI Data mode -#define SPI_MODE0 SPI_MODE_0 -#define SPI_MODE1 SPI_MODE_1 -#define SPI_MODE2 SPI_MODE_2 -#define SPI_MODE3 SPI_MODE_3 - -#ifndef SPI_SPIDEV_DEVICE -#define SPI_SPIDEV_DEVICE "/dev/spidev0.0" -#endif - -// Default to Raspberry Pi -const uint8_t SS = 24; -const uint8_t MOSI = 19; -const uint8_t MISO = 21; -const uint8_t SCK = 23; - -/** - * SPISettings class - */ -class SPISettings -{ - -public: - /** - * @brief SPISettings constructor. - */ - SPISettings() - { - init(SPI_CLOCK_BASE, MSBFIRST, SPI_MODE0); - } - /** - * @brief SPISettings constructor. - * - * @param clock SPI clock speed in Hz. - * @param bitOrder SPI bit order. - * @param dataMode SPI data mode. - */ - SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) - { - init(clock, bitOrder, dataMode); - } - - uint32_t clock; //!< @brief SPI clock. - uint8_t border; //!< @brief SPI bit order. - uint8_t dmode; //!< @brief SPI data mode. - -private: - /** - * @brief Initialized class members. - * - * @param clk SPI clock. - * @param bitOrder SPI bit order. - * @param dataMode SPI data mode. - */ - void init(uint32_t clk, uint8_t bitOrder, uint8_t dataMode) - { - clock = clk; - border = bitOrder; - dmode = dataMode; - } - - friend class SPIDEVClass; -}; - -/** - * SPIDEV class - */ -class SPIDEVClass -{ - -public: - /** - * @brief SPIDEVClass constructor. - */ - SPIDEVClass(); - /** - * @brief Start SPI operations. - */ - static void begin(int busNo=0); - /** - * @brief End SPI operations. - */ - static void end(); - /** - * @brief Sets the SPI bit order. - * - * @param bit_order The desired bit order. - */ - static void setBitOrder(uint8_t bit_order); - /** - * @brief Sets the SPI data mode. - * - * @param data_mode The desired data mode. - */ - static void setDataMode(uint8_t data_mode); - /** - * @brief Sets the SPI clock divider and therefore the SPI clock speed. - * - * @param divider The desired SPI clock divider. - */ - static void setClockDivider(uint16_t divider); - /** - * @brief Sets the chip select pin. - * - * @param csn_chip Specifies the CS chip. - */ - static void chipSelect(int csn_chip); - /** - * @brief Transfer a single byte - * - * @param data Byte to send - * @return Data returned via spi - */ - static uint8_t transfer(uint8_t data); - /** - * @brief Transfer a buffer of data - * - * @param tbuf Transmit buffer - * @param rbuf Receive buffer - * @param len Length of the data - */ - static void transfernb(char* tbuf, char* rbuf, uint32_t len); - /** - * @brief Transfer a buffer of data without an rx buffer - * - * @param buf Pointer to a buffer of data - * @param len Length of the data - */ - static void transfern(char* buf, uint32_t len); - /** - * @brief Start SPI transaction. - * - * @param settings for SPI. - */ - static void beginTransaction(SPISettings settings); - /** - * @brief End SPI transaction. - */ - static void endTransaction(); - /** - * @brief Not implemented. - * - * @param interruptNumber ignored parameter. - */ - static void usingInterrupt(uint8_t interruptNumber); - /** - * @brief Not implemented. - * - * @param interruptNumber ignored parameter. - */ - static void notUsingInterrupt(uint8_t interruptNumber); - -private: - static uint8_t initialized; //!< @brief SPI initialized flag. - static int fd; //!< @brief SPI device file descriptor. - static std::string device; //!< @brief Default SPI device. - static uint8_t mode; //!< @brief SPI mode. - static uint32_t speed; //!< @brief SPI speed. - static uint8_t bit_order; //!< @brief SPI bit order. - static struct spi_ioc_transfer tr; //!< @brief Auxiliar struct for data transfer. - - static void init(); -}; - -extern SPIDEVClass SPIDEV; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/SerialPort.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/SerialPort.cpp deleted file mode 100644 index baa51582..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/SerialPort.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "log.h" -#include "SerialPort.h" - -SerialPort::SerialPort(const char *port, bool isPty) : serialPort(std::string(port)), isPty(isPty) -{ - sd = -1; -} - -void SerialPort::begin(int bauds) -{ - if (!open(bauds)) { - logError("Failed to open serial port.\n"); - exit(1); - } - logDebug("Serial port %s (%d baud) created\n", serialPort.c_str(), bauds); -} - -bool SerialPort::open(int bauds) -{ - speed_t speed; - struct termios options; - - if (isPty) { - sd = posix_openpt(O_RDWR | O_NOCTTY | O_NDELAY); - if (sd < 0) { - logError("Couldn't open a PTY: %s\n", strerror(errno)); - return false; - } - - if (grantpt(sd) != 0) { - logError("Couldn't grant permission to the PTY: %s\n", strerror(errno)); - return false; - } - - if (unlockpt(sd) != 0) { - logError("Couldn't unlock the PTY: %s\n", strerror(errno)); - return false; - } - - /* create a symlink with predictable name to the PTY device */ - unlink(serialPort.c_str()); // remove the symlink if it already exists - if (symlink(ptsname(sd), serialPort.c_str()) != 0) { - logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno, - strerror(errno)); - return false; - } - } else { - if ((sd = ::open(serialPort.c_str(), O_RDWR | O_NOCTTY | O_NDELAY)) == -1) { - logError("Unable to open the serial port %s\n", serialPort.c_str()); - return false; - } - - // nonblocking mode - fcntl(sd, F_SETFL, FNDELAY); - } - - switch (bauds) { - case 50: - speed = B50 ; - break ; - case 75: - speed = B75 ; - break ; - case 110: - speed = B110 ; - break ; - case 134: - speed = B134 ; - break ; - case 150: - speed = B150 ; - break ; - case 200: - speed = B200 ; - break ; - case 300: - speed = B300 ; - break ; - case 600: - speed = B600 ; - break ; - case 1200: - speed = B1200 ; - break ; - case 1800: - speed = B1800 ; - break ; - case 2400: - speed = B2400 ; - break ; - case 9600: - speed = B9600 ; - break ; - case 19200: - speed = B19200 ; - break ; - case 38400: - speed = B38400 ; - break ; - case 57600: - speed = B57600 ; - break ; - case 115200: - speed = B115200 ; - break ; - default: - speed = B115200 ; - break ; - } - - // Get the current options of the port - if (tcgetattr(sd, &options) < 0) { - logError("Couldn't get term attributes: %s\n", strerror(errno)); - return false; - } - - // Clear all the options - bzero(&options, sizeof(options)); - - // Set the baud rate - cfsetispeed(&options, speed); - cfsetospeed(&options, speed); - - // Configure the device : 8 bits, no parity, no control - options.c_cflag |= ( CLOCAL | CREAD | CS8); - // Ignore framing errors, parity errors and BREAK condition on input. - options.c_iflag |= ( IGNPAR | IGNBRK ); - - // Timer unused - options.c_cc[VTIME]=0; - // At least on character before satisfy reading - options.c_cc[VMIN]=0; - - // Set parameters - if (tcsetattr(sd, TCSANOW, &options) < 0) { - logError("Couldn't set term attributes: %s\n", strerror(errno)); - return false; - } - - // flush - if (tcflush(sd, TCIOFLUSH) < 0) { - logError("Couldn't flush serial: %s\n", strerror(errno)); - return false; - } - - usleep(10000); - - return true; -} - -bool SerialPort::setGroupPerm(const char *groupName) -{ - const mode_t ttyPermissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; - - if (sd != -1 && groupName != NULL) { - struct group *devGrp = getgrnam(groupName); - if (devGrp == NULL) { - logError("getgrnam: %s failed. (%d) %s\n", groupName, errno, strerror(errno)); - return false; - } - - const char *dev; - if (isPty) { - dev = ptsname(sd); - } else { - dev = serialPort.c_str(); - } - - int ret = chown(dev, -1, devGrp->gr_gid); - if (ret == -1) { - logError("Could not change PTY owner! (%d) %s\n", errno, strerror(errno)); - return false; - } - - ret = chmod(dev, ttyPermissions); - if (ret != 0) { - logError("Could not change PTY permissions! (%d) %s\n", errno, strerror(errno)); - return false; - } - - return true; - } - return false; -} - -int SerialPort::available() -{ - int nbytes = 0; - - if (ioctl(sd, FIONREAD, &nbytes) < 0) { - logError("Failed to get byte count on serial.\n"); - exit(-1); - } - return nbytes; -} - -int SerialPort::read() -{ - unsigned char c; - - int ret = ::read(sd, &c, 1); - if (ret < 0) { - logError("Serial - read failed: %s\n", strerror(errno)); - } else if (ret == 1) { - return c; - } - - return -1; -} - -size_t SerialPort::write(uint8_t b) -{ - int ret = ::write(sd, &b, 1); - if (ret < 0) { - logError("Serial - write failed: %s\n", strerror(errno)); - } - return ret; -} - -size_t SerialPort::write(const uint8_t *buffer, size_t size) -{ - int ret = ::write(sd, buffer, size); - if (ret < 0) { - logError("Serial - write failed: %s\n", strerror(errno)); - } - return ret; -} - -int SerialPort::peek() -{ - FILE * f = fdopen(sd, "r+"); - int c = getc(f); - if (c == EOF) { - return -1; - } - ungetc(c, f); - return c; -} - -void SerialPort::flush() -{ - // Waits until all output written to sd has been transmitted - if (tcdrain(sd) < 0) { - logError("Couldn't flush serial: %s\n", strerror(errno)); - } -} - -void SerialPort::end() -{ - close(sd); - - if (isPty) { - unlink(serialPort.c_str()); // remove the symlink - } -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/SerialPort.h b/lib/MySensors/hal/architecture/Linux/drivers/core/SerialPort.h deleted file mode 100644 index 540d9b28..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/SerialPort.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef SerialPort_h -#define SerialPort_h - -#include -#include -#include "Stream.h" - -/** - * SerialPort Class - * Class that provides the functionality of arduino Serial library - */ -class SerialPort : public Stream -{ - -private: - int sd; //!< @brief file descriptor number. - std::string serialPort; //!< @brief tty name. - bool isPty; //!< @brief true if serial is pseudo terminal. - -public: - /** - * @brief SerialPort constructor. - */ - SerialPort(const char *port, bool isPty = false); - /** - * @brief Open the serial port and set the data rate in bits per second (baud). - * - * This function will terminate the program on an error. - * - * @param bauds bits per second. - */ - void begin(int bauds); - /** - * @brief Open the serial port and set the data rate in bits per second (baud). - * - * @param bauds bits per second. - * @return @c true if no errors, else @c false. - */ - bool open(int bauds = 115200); - /** - * @brief Grant access to the specified system group for the serial device. - * - * @param groupName system group name. - */ - bool setGroupPerm(const char *groupName); - /** - * @brief Get the number of bytes available. - * - * Get the numberof bytes (characters) available for reading from - * the serial port. - * - * @return number of bytes avalable to read. - */ - int available(); - /** - * @brief Reads 1 byte of incoming serial data. - * - * @return first byte of incoming serial data available. - */ - int read(); - /** - * @brief Writes a single byte to the serial port. - * - * @param b byte to write. - * @return number of bytes written. - */ - size_t write(uint8_t b); - /** - * @brief Writes binary data to the serial port. - * - * @param buffer to write. - * @param size of the buffer. - * @return number of bytes written. - */ - size_t write(const uint8_t *buffer, size_t size); - /** - * @brief - * - * Returns the next byte (character) of incoming serial data without removing it from - * the internal serial buffer. - * - * @return -1 if no data else character in the buffer. - */ - int peek(); - /** - * @brief Remove any data remaining on the serial buffer. - */ - void flush(); - /** - * @brief Disables serial communication. - */ - void end(); -}; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/Server.h b/lib/MySensors/hal/architecture/Linux/drivers/core/Server.h deleted file mode 100644 index 61b14a0e..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/Server.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Server.h - Base class that provides Server - Copyright (c) 2011 Adrian McEwen. All right reserved. - - 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 server_h -#define server_h - -#include "Print.h" - -#if !DOXYGEN -class Server : public Print -{ -public: - virtual void begin() =0; -}; -#endif - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/SoftEeprom.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/SoftEeprom.cpp deleted file mode 100644 index d57af53a..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/SoftEeprom.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include "log.h" -#include "SoftEeprom.h" - -SoftEeprom::SoftEeprom() : _length(0), _fileName(NULL), _values(NULL) -{ -} - -SoftEeprom::SoftEeprom(const SoftEeprom& other) -{ - _fileName = strdup(other._fileName); - - _length = other._length; - _values = new uint8_t[_length]; - for (size_t i = 0; i < _length; ++i) { - _values[i] = other._values[i]; - } -} - -SoftEeprom::~SoftEeprom() -{ - destroy(); -} - -int SoftEeprom::init(const char *fileName, size_t length) -{ - struct stat fileInfo; - - destroy(); - - _fileName = strdup(fileName); - if (_fileName == NULL) { - logError("Error: %s\n", strerror(errno)); - return -1; - } - - _length = length; - _values = new uint8_t[_length]; - - if (stat(_fileName, &fileInfo) != 0) { - //File does not exist. Create it. - logInfo("EEPROM file %s does not exist, creating new file.\n", _fileName); - std::ofstream myFile(_fileName, std::ios::out | std::ios::binary); - if (!myFile) { - logError("Unable to create config file %s.\n", _fileName); - return -1; - } - // Fill the eeprom with 1s - for (size_t i = 0; i < _length; ++i) { - _values[i] = 0xFF; - } - myFile.write((const char*)_values, _length); - myFile.close(); - } else if (fileInfo.st_size < 0 || (size_t)fileInfo.st_size != _length) { - logError("EEPROM file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n", - _fileName, _length); - destroy(); - return -1; - } else { - //Read config into local memory. - std::ifstream myFile(_fileName, std::ios::in | std::ios::binary); - if (!myFile) { - logError("Unable to open EEPROM file %s for reading.\n", _fileName); - return -1; - } - myFile.read((char*)_values, _length); - myFile.close(); - } - - return 0; -} - -void SoftEeprom::destroy() -{ - if (_values) { - delete[] _values; - _values = NULL; - } - if (_fileName) { - free(_fileName); - _fileName = NULL; - } - _length = 0; -} - -void SoftEeprom::readBlock(void* buf, void* addr, size_t length) -{ - unsigned long int offs = reinterpret_cast(addr); - - if (!length) { - logError("EEPROM being read without being initialized!\n"); - return; - } - - if (offs + length <= _length) { - memcpy(buf, _values+offs, length); - } -} - -void SoftEeprom::writeBlock(void* buf, void* addr, size_t length) -{ - unsigned long int offs = reinterpret_cast(addr); - - if (!length) { - logError("EEPROM being written without being initialized!\n"); - return; - } - - if (offs + length <= _length) { - if (memcmp(_values+offs, buf, length) == 0) { - return; - } - - memcpy(_values+offs, buf, length); - - std::ofstream myFile(_fileName, std::ios::out | std::ios::in | std::ios::binary); - if (!myFile) { - logError("Unable to write config to file %s.\n", _fileName); - return; - } - myFile.seekp(offs); - myFile.write((const char*)buf, length); - myFile.close(); - } -} - -uint8_t SoftEeprom::readByte(int addr) -{ - uint8_t value = 0xFF; - readBlock(&value, reinterpret_cast(addr), 1); - return value; -} - -void SoftEeprom::writeByte(int addr, uint8_t value) -{ - uint8_t curr = readByte(addr); - if (curr != value) { - writeBlock(&value, reinterpret_cast(addr), 1); - } -} - -SoftEeprom& SoftEeprom::operator=(const SoftEeprom& other) -{ - if (this != &other) { - delete[] _values; - free(_fileName); - - _fileName = strdup(other._fileName); - - _length = other._length; - _values = new uint8_t[_length]; - for (size_t i = 0; i < _length; ++i) { - _values[i] = other._values[i]; - } - } - return *this; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/SoftEeprom.h b/lib/MySensors/hal/architecture/Linux/drivers/core/SoftEeprom.h deleted file mode 100644 index cd32cd63..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/SoftEeprom.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** -* This a software emulation of EEPROM that uses a file for data storage. -* A copy of the eeprom values are also held in memory for faster reading. -*/ - -#ifndef SoftEeprom_h -#define SoftEeprom_h - -#include - -/** - * SoftEeprom class - */ -class SoftEeprom -{ - -public: - /** - * @brief SoftEeprom constructor. - */ - SoftEeprom(); - /** - * @brief SoftEeprom copy constructor. - */ - SoftEeprom(const SoftEeprom& other); - /** - * @brief SoftEeprom destructor. - */ - ~SoftEeprom(); - /** - * @brief Initializes the eeprom class. - * - * @param fileName filepath where the data is saved. - * @param length eeprom size in bytes. - * @return 0 if SUCCESS or -1 if FAILURE. - */ - int init(const char *fileName, size_t length); - /** - * @brief Clear all allocated memory variables. - * - */ - void destroy(); - /** - * @brief Read a block of bytes from eeprom. - * - * @param buf buffer to copy to. - * @param addr eeprom address to read from. - * @param length number of bytes to read. - */ - void readBlock(void* buf, void* addr, size_t length); - /** - * @brief Write a block of bytes to eeprom. - * - * @param buf buffer to read from. - * @param addr eeprom address to write to. - * @param length number of bytes to write. - */ - void writeBlock(void* buf, void* addr, size_t length); - /** - * @brief Read a byte from eeprom. - * - * @param addr eeprom address to read from. - * @return the read byte. - */ - uint8_t readByte(int addr); - /** - * @brief Write a byte to eeprom. - * - * @param addr eeprom address to write to. - * @param value to write. - */ - void writeByte(int addr, uint8_t value); - /** - * @brief Overloaded assign operator. - * - */ - SoftEeprom& operator=(const SoftEeprom& other); - -private: - size_t _length; //!< @brief Eeprom max size. - char *_fileName; //!< @brief file where the eeprom values are stored. - uint8_t *_values; //!< @brief copy of the eeprom values held in memory for a faster reading. -}; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/StdInOutStream.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/StdInOutStream.cpp deleted file mode 100644 index 905f3d3d..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/StdInOutStream.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include -#include "StdInOutStream.h" - -void StdInOutStream::begin(int baud) -{ - (void)baud; -} - -int StdInOutStream::available() -{ - return 1; -} - -int StdInOutStream::read() -{ - return getchar(); -} - -size_t StdInOutStream::write(uint8_t b) -{ - return (size_t)::printf("%c", b); -} - -int StdInOutStream::peek() -{ - return -1; -} - -void StdInOutStream::flush() -{ - fflush(stdout); -} - -void StdInOutStream::end() -{ - flush(); -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/StdInOutStream.h b/lib/MySensors/hal/architecture/Linux/drivers/core/StdInOutStream.h deleted file mode 100644 index 8dab724c..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/StdInOutStream.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef StdInOutStream_h -#define StdInOutStream_h - -#include -#include -#include -#include "Stream.h" - -/** - * @brief A class that prints to stdout and reads from stdin - */ -class StdInOutStream : public Stream -{ - -public: - /** - * @brief This function does nothing. - * - * @param baud Ignored parameter. - */ - void begin(int baud); - /** - * @brief This function does nothing. - * - * @return always returns 1. - */ - int available(); - /** - * @brief Reads 1 key pressed from the keyboard. - * - * @return key character pressed cast to an int. - */ - int read(); - /** - * @brief Writes a single byte to stdout. - * - * @param b byte to write. - * @return -1 if error else, number of bytes written. - */ - size_t write(uint8_t b); - /** - * @brief Not supported. - * - * @return always returns -1. - */ - int peek(); - /** - * @brief Flush stdout. - */ - void flush(); - /** - * @brief Nothing to do, flush stdout. - */ - void end(); -}; - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/Stream.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/Stream.cpp deleted file mode 100644 index c16fe0c2..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/Stream.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* - Stream.cpp - adds parsing methods to Stream class - Copyright (c) 2008 David A. Mellis. All right reserved. - - 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 - - Created July 2011 - parsing functions based on TextFinder library by Michael Margolis - Modified August 2016 by Marcelo Aquino for MySensors use - */ - -#include -#include - -#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait -#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field - -// private method to read stream with timeout -int Stream::timedRead() -{ - _startMillis = millis(); - do { - int c; - c = read(); - if(c >= 0) { - return c; - } - yield(); - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout -} - -// private method to peek stream with timeout -int Stream::timedPeek() -{ - _startMillis = millis(); - do { - int c; - c = peek(); - if(c >= 0) { - return c; - } - yield(); - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout -} - -// returns peek of the next digit in the stream or -1 if timeout -// discards non-numeric characters -int Stream::peekNextDigit() -{ - while(1) { - int c; - c = timedPeek(); - if(c < 0) { - return c; // timeout - } - if(c == '-') { - return c; - } - if(c >= '0' && c <= '9') { - return c; - } - read(); // discard non-numeric - } -} - -// Public Methods -////////////////////////////////////////////////////////////// - -void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait -{ - _timeout = timeout; -} - -// find returns true if the target string is found -bool Stream::find(const char *target) -{ - return findUntil(target, (char*) ""); -} - -// reads data from the stream until the target string of given length is found -// returns true if target string is found, false if timed out -bool Stream::find(const char *target, size_t length) -{ - return findUntil(target, length, NULL, 0); -} - -// as find but search ends if the terminator string is found -bool Stream::findUntil(const char *target, const char *terminator) -{ - return findUntil(target, strlen(target), terminator, strlen(terminator)); -} - -// reads data from the stream until the target string of the given length is found -// search terminated if the terminator string is found -// returns true if target string is found, false if terminated or timed out -bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, - size_t termLen) -{ - size_t index = 0; // maximum target string length is 64k bytes! - size_t termIndex = 0; - int c; - - if(*target == 0) { - return true; // return true if target is a null string - } - while((c = timedRead()) > 0) { - - if(c != target[index]) { - index = 0; // reset index if any char does not match - } - if(c == target[index]) { - //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); - if(++index >= targetLen) { // return true if all chars in the target match - return true; - } - } - - if(termLen > 0 && c == terminator[termIndex]) { - if(++termIndex >= termLen) { - return false; // return false if terminate string found before target string - } - } else { - termIndex = 0; - } - } - return false; -} - -// returns the first valid (long) integer value from the current position. -// initial characters that are not digits (or the minus sign) are skipped -// function is terminated by the first character that is not a digit. -long Stream::parseInt() -{ - return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) -} - -// as above but a given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -long Stream::parseInt(char skipChar) -{ - bool isNegative = false; - long value = 0; - int c; - - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) { - return 0; // zero returned if timeout - } - - do { - if(c == skipChar) { - // ignore this charactor - } else if(c == '-') { - isNegative = true; - } else if(c >= '0' && c <= '9') { // is c a digit? - value = value * 10 + c - '0'; - } - read(); // consume the character we got with peek - c = timedPeek(); - } while((c >= '0' && c <= '9') || c == skipChar); - - if(isNegative) { - value = -value; - } - return value; -} - -// as parseInt but returns a floating point value -float Stream::parseFloat() -{ - return parseFloat(NO_SKIP_CHAR); -} - -// as above but the given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -float Stream::parseFloat(char skipChar) -{ - bool isNegative = false; - bool isFraction = false; - long value = 0; - int c; - float fraction = 1.0; - - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) { - return 0; // zero returned if timeout - } - - do { - if(c == skipChar) { - // ignore - } else if(c == '-') { - isNegative = true; - } else if(c == '.') { - isFraction = true; - } else if(c >= '0' && c <= '9') { // is c a digit? - value = value * 10 + c - '0'; - if(isFraction) { - fraction *= 0.1; - } - } - read(); // consume the character we got with peek - c = timedPeek(); - } while((c >= '0' && c <= '9') || c == '.' || c == skipChar); - - if(isNegative) { - value = -value; - } - if(isFraction) { - return value * fraction; - } else { - return value; - } -} - -// read characters from stream into buffer -// terminates if length characters have been read, or timeout (see setTimeout) -// returns the number of characters placed in the buffer -// the buffer is NOT null terminated. -// -size_t Stream::readBytes(char *buffer, size_t length) -{ - size_t count = 0; - while(count < length) { - int c = timedRead(); - if(c < 0) { - break; - } - *buffer++ = (char) c; - count++; - } - return count; -} - -// as readBytes with terminator character -// terminates if length characters have been read, timeout, or if the terminator character detected -// returns the number of characters placed in the buffer (0 means no valid data found) - -size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) -{ - if(length < 1) { - return 0; - } - size_t index = 0; - while(index < length) { - int c = timedRead(); - if(c < 0 || c == terminator) { - break; - } - *buffer++ = (char) c; - index++; - } - return index; // return number of characters, not including null terminator -} - -std::string Stream::readString() -{ - std::string ret; - int c = timedRead(); - while(c >= 0) { - ret += (char) c; - c = timedRead(); - } - return ret; -} - -std::string Stream::readStringUntil(char terminator) -{ - std::string ret; - int c = timedRead(); - while(c >= 0 && c != terminator) { - ret += (char) c; - c = timedRead(); - } - return ret; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/Stream.h b/lib/MySensors/hal/architecture/Linux/drivers/core/Stream.h deleted file mode 100644 index 0a46b727..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/Stream.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - Stream.h - base class for character-based streams. - Copyright (c) 2010 David A. Mellis. All right reserved. - - 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 - - parsing functions based on TextFinder library by Michael Margolis - Modified August 2016 by Marcelo Aquino for MySensors use - */ - -#ifndef Stream_h -#define Stream_h - -#include -#include -#include "Print.h" - -// compatability macros for testing -/* - #define getInt() parseInt() - #define getInt(skipChar) parseInt(skipchar) - #define getFloat() parseFloat() - #define getFloat(skipChar) parseFloat(skipChar) - #define getString( pre_string, post_string, buffer, length) - readBytesBetween( pre_string, terminator, buffer, length) - */ - -#if !DOXYGEN -class Stream: public Print -{ -protected: - unsigned long - _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout - -public: - virtual int available() = 0; - virtual int read() = 0; - virtual int peek() = 0; - virtual void flush() = 0; - - Stream() - { - _timeout = 1000; - _startMillis = 0; - } - - // parsing methods - - void setTimeout(unsigned long - timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - - bool find(const char *target); // reads data from the stream until the target string is found - bool find(uint8_t *target) - { - return find((char *) target); - } - // returns true if target string is found, false if timed out (see setTimeout) - - bool find(const char *target, size_t - length); // reads data from the stream until the target string of given length is found - bool find(const uint8_t *target, size_t length) - { - return find((char *) target, length); - } - // returns true if target string is found, false if timed out - - bool find(char target) - { - return find (&target, 1); - } - - bool findUntil(const char *target, - const char *terminator); // as find but search ends if the terminator string is found - bool findUntil(const uint8_t *target, const char *terminator) - { - return findUntil((char *) target, terminator); - } - - bool findUntil(const char *target, size_t targetLen, const char *terminate, - size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) - { - return findUntil((char *) target, targetLen, terminate, termLen); - } - - long parseInt(); // returns the first valid (long) integer value from the current position. - // initial characters that are not digits (or the minus sign) are skipped - // integer is terminated by the first character that is not a digit. - - float parseFloat(); // float version of parseInt - - virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer - virtual size_t readBytes(uint8_t *buffer, size_t length) - { - return readBytes((char *) buffer, length); - } - // terminates if length characters have been read or timeout (see setTimeout) - // returns the number of characters placed in the buffer (0 means no valid data found) - - size_t readBytesUntil(char terminator, char *buffer, - size_t length); // as readBytes with terminator character - size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) - { - return readBytesUntil(terminator, (char *) buffer, length); - } - // terminates if length characters have been read, timeout, or if the terminator character detected - // returns the number of characters placed in the buffer (0 means no valid data found) - - // Arduino String functions to be added here - std::string readString(); - std::string readStringUntil(char terminator); - -protected: - long parseInt(char skipChar); // as above but the given skipChar is ignored - // as above but the given skipChar is ignored - // this allows format characters (typically commas) in values to be ignored - - float parseFloat(char skipChar); // as above but the given skipChar is ignored -}; -#endif - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/compatibility.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/compatibility.cpp deleted file mode 100644 index febd3d47..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/compatibility.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include "Arduino.h" - -// For millis() -static unsigned long millis_at_start = 0; - -void yield(void) {} - -unsigned long millis(void) -{ - timeval curTime; - - if (millis_at_start == 0) { - gettimeofday(&curTime, NULL); - millis_at_start = curTime.tv_sec; - } - - gettimeofday(&curTime, NULL); - return ((curTime.tv_sec - millis_at_start) * 1000) + (curTime.tv_usec / 1000); -} - -unsigned long micros() -{ - timeval curTime; - - if (millis_at_start == 0) { - gettimeofday(&curTime, NULL); - millis_at_start = curTime.tv_sec; - } - - gettimeofday(&curTime, NULL); - return ((curTime.tv_sec - millis_at_start) * 1000000) + (curTime.tv_usec); -} - -void _delay_milliseconds(unsigned int millis) -{ - struct timespec sleeper; - - sleeper.tv_sec = (time_t)(millis / 1000); - sleeper.tv_nsec = (long)(millis % 1000) * 1000000; - nanosleep(&sleeper, NULL); -} - -void _delay_microseconds(unsigned int micro) -{ - struct timespec sleeper; - - sleeper.tv_sec = (time_t)(micro / 1000000); - sleeper.tv_nsec = (long)(micro % 1000000) * 1000; - nanosleep(&sleeper, NULL); -} - -void randomSeed(unsigned long seed) -{ - if (seed != 0) { - srand(seed); - } -} - -long randMax(long howbig) -{ - if (howbig == 0) { - return 0; - } - return rand() % howbig; -} - -long randMinMax(long howsmall, long howbig) -{ - if (howsmall >= howbig) { - return howsmall; - } - long diff = howbig - howsmall; - return randMax(diff) + howsmall; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/config.c b/lib/MySensors/hal/architecture/Linux/drivers/core/config.c deleted file mode 100644 index 23c717e5..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/config.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on mosquitto project, Copyright (c) 2012 Roger Light - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include "log.h" - -static int _config_create(const char *config_file); -static int _config_parse_int(char *token, const char *name, int *value); -static int _config_parse_string(char *token, const char *name, char **value); - -int config_parse(const char *config_file) -{ - FILE *fptr; - char buf[1024]; - struct stat fileInfo; - - if (stat(config_file, &fileInfo) != 0) { - //File does not exist. Create it. - logInfo("Config file %s does not exist, creating new file.\n", config_file); - _config_create(config_file); - } - - fptr = fopen(config_file, "rt"); - if (!fptr) { - logError("Error opening config file \"%s\".\n", config_file); - return -1; - } - - conf.verbose = 7; - conf.log_pipe = 0; - conf.log_pipe_file = NULL; - conf.syslog = 0; - conf.eeprom_file = NULL; - conf.eeprom_size = 0; - conf.soft_hmac_key = NULL; - conf.soft_serial_key = NULL; - conf.aes_key = NULL; - - while (fgets(buf, 1024, fptr)) { - if (buf[0] != '#' && buf[0] != 10 && buf[0] != 13) { - while (buf[strlen(buf)-1] == 10 || buf[strlen(buf)-1] == 13) { - buf[strlen(buf)-1] = 0; - } - - if (!strncmp(buf, "verbose=", 8)) { - char *verbose = NULL; - if (_config_parse_string(&(buf[8]), "verbose", &verbose)) { - fclose(fptr); - return -1; - } else { - if (!strncmp(verbose, "err", 3)) { - conf.verbose = 3; - } else if (!strncmp(verbose, "warn", 4)) { - conf.verbose = 4; - } else if (!strncmp(verbose, "notice", 6)) { - conf.verbose = 5; - } else if (!strncmp(verbose, "info", 4)) { - conf.verbose = 6; - } else if (!strncmp(verbose, "debug", 5)) { - conf.verbose = 7; - } else { - logError("Invalid value for verbose in configuration.\n"); - fclose(fptr); - free(verbose); - return -1; - } - free(verbose); - } - } else if (!strncmp(buf, "log_file=", 9)) { - if (_config_parse_int(&(buf[9]), "log_file", &conf.log_file)) { - fclose(fptr); - return -1; - } else { - if (conf.log_file != 0 && conf.log_file != 1) { - logError("log_file must be 1 or 0 in configuration.\n"); - fclose(fptr); - return -1; - } - } - } else if (!strncmp(buf, "log_filepath=", 13)) { - if (_config_parse_string(&(buf[13]), "log_filepath", &conf.log_filepath)) { - fclose(fptr); - return -1; - } - } else if (!strncmp(buf, "log_pipe=", 9)) { - if (_config_parse_int(&(buf[9]), "log_pipe", &conf.log_pipe)) { - fclose(fptr); - return -1; - } else { - if (conf.log_pipe != 0 && conf.log_pipe != 1) { - logError("log_pipe must be 1 or 0 in configuration.\n"); - fclose(fptr); - return -1; - } - } - } else if (!strncmp(buf, "log_pipe_file=", 14)) { - if (_config_parse_string(&(buf[14]), "log_pipe_file", &conf.log_pipe_file)) { - fclose(fptr); - return -1; - } - } else if (!strncmp(buf, "syslog=", 7)) { - if (_config_parse_int(&(buf[7]), "syslog", &conf.syslog)) { - fclose(fptr); - return -1; - } else { - if (conf.syslog != 0 && conf.syslog != 1) { - logError("syslog must be 1 or 0 in configuration.\n"); - fclose(fptr); - return -1; - } - } - } else if (!strncmp(buf, "eeprom_file=", 12)) { - if (_config_parse_string(&(buf[12]), "eeprom_file", &conf.eeprom_file)) { - fclose(fptr); - return -1; - } - } else if (!strncmp(buf, "eeprom_size=", 12)) { - if (_config_parse_int(&(buf[12]), "eeprom_size", &conf.eeprom_size)) { - fclose(fptr); - return -1; - } else { - if (conf.eeprom_size <= 0) { - logError("eeprom_size value must be greater than 0 in configuration.\n"); - fclose(fptr); - return -1; - } - } - } else if (!strncmp(buf, "soft_hmac_key=", 14)) { - if (_config_parse_string(&(buf[14]), "soft_hmac_key", &conf.soft_hmac_key)) { - fclose(fptr); - return -1; - } - } else if (!strncmp(buf, "soft_serial_key=", 16)) { - if (_config_parse_string(&(buf[16]), "soft_serial_key", &conf.soft_serial_key)) { - fclose(fptr); - return -1; - } - } else if (!strncmp(buf, "aes_key=", 8)) { - if (_config_parse_string(&(buf[8]), "aes_key", &conf.aes_key)) { - fclose(fptr); - return -1; - } - } else { - logWarning("Unknown config option \"%s\".\n", buf); - } - } - } - fclose(fptr); - - if (!conf.eeprom_file) { - logError("No eeprom_file found in configuration.\n"); - return -1; - } - - if (conf.log_file && !conf.log_filepath) { - logError("log_filepath must be set if you enable log_file in configuration.\n"); - return -1; - } - - if (conf.log_pipe && !conf.log_pipe_file) { - logError("log_pipe_file must be set if you enable log_pipe in configuration.\n"); - return -1; - } - - return 0; -} - -void config_cleanup(void) -{ - if (conf.log_filepath) { - free(conf.log_filepath); - } - if (conf.log_pipe_file) { - free(conf.log_pipe_file); - } - if (conf.eeprom_file) { - free(conf.eeprom_file); - } - if (conf.soft_hmac_key) { - free(conf.soft_hmac_key); - } - if (conf.soft_serial_key) { - free(conf.soft_serial_key); - } - if (conf.aes_key) { - free(conf.aes_key); - } -} - -int _config_create(const char *config_file) -{ - FILE *myFile; - int ret; - - const char default_conf[] = "# Logging\n" \ - "# Verbosity: debug,info,notice,warn,err\n" \ - "verbose=debug\n" \ - "\n" \ - "# Enable logging to a file.\n" \ - "log_file=0\n" \ - "# Log file path.\n" \ - "log_filepath=/tmp/mysgw.log\n" \ - "\n" \ - "# Enable logging to a named pipe.\n" \ - "# Use this option to view your gateway's log messages\n" \ - "# from the log_pipe_file defined bellow.\n" \ - "# To do so, run the following command on another terminal:\n" \ - "# cat \"log_pipe_file\"\n" \ - "log_pipe=0\n" \ - "log_pipe_file=/tmp/mysgw.pipe\n" \ - "\n" \ - "# Enable logging to syslog.\n" \ - "syslog=0\n" \ - "\n" \ - "# EEPROM settings\n" \ - "eeprom_file=/etc/mysensors.eeprom\n" \ - "eeprom_size=1024\n" \ - "\n" \ - "# Software signing settings\n" \ - "# Note: The gateway must have been built with signing\n" \ - "# support to use the options below.\n" \ - "#\n" \ - "# To generate a HMAC key run mysgw with: --gen-soft-hmac-key\n" \ - "# copy the new key in the line below and uncomment it.\n" \ - "#soft_hmac_key=\n" \ - "# To generate a serial key run mysgw with: --gen-soft-serial-key\n" \ - "# copy the new key in the line below and uncomment it.\n" \ - "#soft_serial_key=\n" \ - "\n" \ - "# Encryption settings\n" \ - "# Note: The gateway must have been built with encryption\n" \ - "# support to use the options below.\n" \ - "#\n" \ - "# To generate a AES key run mysgw with: --gen-aes-key\n" \ - "# copy the new key in the line below and uncomment it.\n" \ - "#aes_key=\n"; - - myFile = fopen(config_file, "w"); - if (!myFile) { - logError("Unable to create config file %s.\n", config_file); - return -1; - } - ret = fputs(default_conf, myFile); - fclose(myFile); - - return (ret > 0); -} - -int _config_parse_int(char *token, const char *name, int *value) -{ - if (token) { - *value = atoi(token); - } else { - logError("Empty %s value in configuration.\n", name); - return 1; - } - - return 0; -} - -int _config_parse_string(char *token, const char *name, char **value) -{ - if (token) { - if (*value) { - logError("Duplicate %s value in configuration.\n", name); - return 1; - } - while (token[0] == ' ' || token[0] == '\t') { - token++; - } - *value = strdup(token); - if (!*value) { - logError("Out of memory.\n"); - return 1; - } - } else { - logError("Empty %s value in configuration.\n", name); - return 1; - } - return 0; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/config.h b/lib/MySensors/hal/architecture/Linux/drivers/core/config.h deleted file mode 100644 index ddea21c3..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/config.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef CONFIG_H -#define CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -struct config { - int verbose; - int log_file; - char *log_filepath; - int log_pipe; - char *log_pipe_file; - int syslog; - char *eeprom_file; - int eeprom_size; - char *soft_hmac_key; - char *soft_serial_key; - char *aes_key; -} conf; - -int config_parse(const char *config_file); -void config_cleanup(void); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/interrupt.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/interrupt.cpp deleted file mode 100644 index f2efce2c..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/interrupt.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on wiringPi Copyright (c) 2012 Gordon Henderson. - */ - -#include "interrupt.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "log.h" - -struct ThreadArgs { - void (*func)(); - int gpioPin; -}; - -volatile bool interruptsEnabled = true; -static pthread_mutex_t intMutex = PTHREAD_MUTEX_INITIALIZER; - -static pthread_t *threadIds[64] = {NULL}; - -// sysFds: -// Map a file descriptor from the /sys/class/gpio/gpioX/value -static int sysFds[64] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - -/* - * Part of wiringPi: Simple way to get your program running at high priority - * with realtime schedulling. - */ -int piHiPri(const int pri) -{ - struct sched_param sched ; - - memset (&sched, 0, sizeof(sched)) ; - - if (pri > sched_get_priority_max (SCHED_RR)) { - sched.sched_priority = sched_get_priority_max (SCHED_RR) ; - } else { - sched.sched_priority = pri ; - } - - return sched_setscheduler (0, SCHED_RR, &sched) ; -} - -void *interruptHandler(void *args) -{ - int fd; - struct pollfd polls; - char c; - struct ThreadArgs *arguments = (struct ThreadArgs *)args; - int gpioPin = arguments->gpioPin; - void (*func)() = arguments->func; - delete arguments; - - (void)piHiPri(55); // Only effective if we run as root - - if ((fd = sysFds[gpioPin]) == -1) { - logError("Failed to attach interrupt for pin %d\n", gpioPin); - return NULL; - } - - // Setup poll structure - polls.fd = fd; - polls.events = POLLPRI | POLLERR; - - while (1) { - // Wait for it ... - int ret = poll(&polls, 1, -1); - if (ret < 0) { - logError("Error waiting for interrupt: %s\n", strerror(errno)); - break; - } - // Do a dummy read to clear the interrupt - // A one character read appars to be enough. - if (lseek (fd, 0, SEEK_SET) < 0) { - logError("Interrupt handler error: %s\n", strerror(errno)); - break; - } - if (read (fd, &c, 1) < 0) { - logError("Interrupt handler error: %s\n", strerror(errno)); - break; - } - // Call user function. - pthread_mutex_lock(&intMutex); - if (interruptsEnabled) { - pthread_mutex_unlock(&intMutex); - func(); - } else { - pthread_mutex_unlock(&intMutex); - } - } - - close(fd); - - return NULL; -} - -void attachInterrupt(uint8_t gpioPin, void (*func)(), uint8_t mode) -{ - FILE *fd; - char fName[40]; - char c; - int count, i; - - if (threadIds[gpioPin] == NULL) { - threadIds[gpioPin] = new pthread_t; - } else { - // Cancel the existing thread for that pin - pthread_cancel(*threadIds[gpioPin]); - // Wait a bit - usleep(1000); - } - - // Export pin for interrupt - if ((fd = fopen("/sys/class/gpio/export", "w")) == NULL) { - logError("attachInterrupt: Unable to export pin %d for interrupt: %s\n", gpioPin, strerror(errno)); - exit(1); - } - fprintf(fd, "%d\n", gpioPin); - fclose(fd); - - // Wait a bit the system to create /sys/class/gpio/gpio - usleep(1000); - - snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/direction", gpioPin) ; - if ((fd = fopen (fName, "w")) == NULL) { - logError("attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n", - gpioPin, strerror(errno)); - exit(1) ; - } - fprintf(fd, "in\n") ; - fclose(fd) ; - - snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/edge", gpioPin) ; - if ((fd = fopen(fName, "w")) == NULL) { - logError("attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", gpioPin, - strerror(errno)); - exit(1) ; - } - - switch (mode) { - case CHANGE: - fprintf(fd, "both\n"); - break; - case FALLING: - fprintf(fd, "falling\n"); - break; - case RISING: - fprintf(fd, "rising\n"); - break; - case NONE: - fprintf(fd, "none\n"); - break; - default: - logError("attachInterrupt: Invalid mode\n"); - fclose(fd); - return; - } - fclose(fd); - - if (sysFds[gpioPin] == -1) { - snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/value", gpioPin); - if ((sysFds[gpioPin] = open(fName, O_RDWR)) < 0) { - logError("Error reading pin %d: %s\n", gpioPin, strerror(errno)); - exit(1); - } - } - - // Clear any initial pending interrupt - ioctl(sysFds[gpioPin], FIONREAD, &count); - for (i = 0; i < count; ++i) { - if (read(sysFds[gpioPin], &c, 1) == -1) { - logError("attachInterrupt: failed to read pin status: %s\n", strerror(errno)); - } - } - - struct ThreadArgs *threadArgs = new struct ThreadArgs; - threadArgs->func = func; - threadArgs->gpioPin = gpioPin; - - // Create a thread passing the pin and function - pthread_create(threadIds[gpioPin], NULL, interruptHandler, (void *)threadArgs); -} - -void detachInterrupt(uint8_t gpioPin) -{ - // Cancel the thread - if (threadIds[gpioPin] != NULL) { - pthread_cancel(*threadIds[gpioPin]); - delete threadIds[gpioPin]; - threadIds[gpioPin] = NULL; - } - - // Close filehandle - if (sysFds[gpioPin] != -1) { - close(sysFds[gpioPin]); - sysFds[gpioPin] = -1; - } - - FILE *fp = fopen("/sys/class/gpio/unexport", "w"); - if (fp == NULL) { - logError("Unable to unexport pin %d for interrupt\n", gpioPin); - exit(1); - } - fprintf(fp, "%d", gpioPin); - fclose(fp); -} - -void interrupts() -{ - pthread_mutex_lock(&intMutex); - interruptsEnabled = true; - pthread_mutex_unlock(&intMutex); -} - -void noInterrupts() -{ - pthread_mutex_lock(&intMutex); - interruptsEnabled = false; - pthread_mutex_unlock(&intMutex); -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/interrupt.h b/lib/MySensors/hal/architecture/Linux/drivers/core/interrupt.h deleted file mode 100644 index 0a4fc01c..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/interrupt.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on wiringPi Copyright (c) 2012 Gordon Henderson. - */ - -#ifndef interrupt_h -#define interrupt_h - -#include - -#define CHANGE 1 -#define FALLING 2 -#define RISING 3 -#define NONE 4 - -#ifdef __cplusplus -extern "C" { -#endif - -void attachInterrupt(uint8_t gpioPin, void(*func)(), uint8_t mode); -void detachInterrupt(uint8_t gpioPin); -void interrupts(); -void noInterrupts(); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/log.c b/lib/MySensors/hal/architecture/Linux/drivers/core/log.c deleted file mode 100644 index 7f6c6b40..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/log.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "log.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const char *_log_level_colors[] = { - "\x1b[1;5;91m", "\x1b[1;91m", "\x1b[91m", "\x1b[31m", "\x1b[33m", "\x1b[34m", "\x1b[32m", "\x1b[36m" -}; -static const char *_log_level_names[] = { - "EMERGENCY", "ALERT", "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG" -}; -static uint8_t _log_quiet = 0; -static uint8_t _log_level = LOG_DEBUG; -static uint8_t _log_syslog = 0; - -static uint8_t _log_pipe = 0; -static char *_log_pipe_file = NULL; -static int _log_pipe_fd = -1; - -static FILE *_log_file_fp = NULL; - -void logSetQuiet(uint8_t enable) -{ - _log_quiet = enable ? 1 : 0; -} - -void logSetLevel(int level) -{ - if (level < LOG_EMERG || level > LOG_DEBUG) { - return; - } - - _log_level = level; -} - -void logSetSyslog(int options, int facility) -{ - openlog(NULL, options, facility); - _log_syslog = 1; -} - -int logSetPipe(char *pipe_file) -{ - if (pipe_file == NULL) { - return -1; - } - - _log_pipe_file = strdup(pipe_file); - if (_log_pipe_file == NULL) { - return -1; - } - - int ret = mkfifo(_log_pipe_file, 0666); - if (ret == 0) { - _log_pipe = 1; - } - - return ret; -} - -int logSetFile(char *file) -{ - if (file == NULL) { - return -1; - } - - _log_file_fp = fopen(file, "a"); - if (_log_file_fp == NULL) { - return errno; - } - - return 0; -} - -void logClose(void) -{ - if (_log_syslog) { - closelog(); - _log_syslog = 0; - } - - if (_log_pipe) { - if (_log_pipe_fd > 0) { - close(_log_pipe_fd); - } - /* remove the FIFO */ - unlink(_log_pipe_file); - _log_pipe = 0; - } - if (_log_pipe_file != NULL) { - free(_log_pipe_file); - _log_pipe_file = NULL; - } - - if (_log_file_fp != NULL) { - fclose(_log_file_fp); - _log_file_fp = NULL; - } -} - -void vlog(int level, const char *fmt, va_list args) -{ - if (_log_level < level) { - return; - } - - if (!_log_quiet || _log_file_fp != NULL) { - /* Get current time */ - time_t t = time(NULL); - struct tm *lt = localtime(&t); - - char date[16]; - date[strftime(date, sizeof(date), "%b %d %H:%M:%S", lt)] = '\0'; - - if (_log_file_fp != NULL) { - fprintf(_log_file_fp, "%s %-5s ", date, _log_level_names[level]); - vfprintf(_log_file_fp, fmt, args); - fflush(_log_file_fp); - } - - if (!_log_quiet) { -#ifdef LOG_DISABLE_COLOR - (void)_log_level_colors; - fprintf(stderr, "%s %-5s ", date, _log_level_names[level]); - vfprintf(stderr, fmt, args); -#else - fprintf(stderr, "%s %s%-5s\x1b[0m ", date, _log_level_colors[level], _log_level_names[level]); - vfprintf(stderr, fmt, args); -#endif - } - } - - if (_log_syslog) { - vsyslog(level, fmt, args); - } - - if (_log_pipe) { - if (_log_pipe_fd < 0) { - _log_pipe_fd = open(_log_pipe_file, O_WRONLY | O_NONBLOCK); - } - if (_log_pipe_fd > 0) { - if (vdprintf(_log_pipe_fd, fmt, args) < 0) { - close(_log_pipe_fd); - _log_pipe_fd = -1; - } - } - - } -} - -void -#ifdef __GNUC__ -__attribute__((format(printf, 1, 2))) -#endif -logEmergency(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vlog(LOG_EMERG, fmt, args); - va_end(args); -} - -void -#ifdef __GNUC__ -__attribute__((format(printf, 1, 2))) -#endif -logAlert(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vlog(LOG_ALERT, fmt, args); - va_end(args); -} - -void -#ifdef __GNUC__ -__attribute__((format(printf, 1, 2))) -#endif -logCritical(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vlog(LOG_CRIT, fmt, args); - va_end(args); -} - -void -#ifdef __GNUC__ -__attribute__((format(printf, 1, 2))) -#endif -logError(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vlog(LOG_ERR, fmt, args); - va_end(args); -} - -void -#ifdef __GNUC__ -__attribute__((format(printf, 1, 2))) -#endif -logWarning(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vlog(LOG_WARNING, fmt, args); - va_end(args); -} - -void -#ifdef __GNUC__ -__attribute__((format(printf, 1, 2))) -#endif -logNotice(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vlog(LOG_NOTICE, fmt, args); - va_end(args); -} - -void -#ifdef __GNUC__ -__attribute__((format(printf, 1, 2))) -#endif -logInfo(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vlog(LOG_INFO, fmt, args); - va_end(args); -} - -void -#ifdef __GNUC__ -__attribute__((format(printf, 1, 2))) -#endif -logDebug(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vlog(LOG_DEBUG, fmt, args); - va_end(args); -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/log.h b/lib/MySensors/hal/architecture/Linux/drivers/core/log.h deleted file mode 100644 index 584c4b8e..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/log.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef LOG_H -#define LOG_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define vlogError(...) vlog(LOG_ERR, __VA_ARGS__) -#define vlogWarning(...) vlog(LOG_WARNING, __VA_ARGS__) -#define vlogNotice(...) vlog(LOG_NOTICE, __VA_ARGS__) -#define vlogInfo(...) vlog(LOG_INFO, __VA_ARGS__) -#define vlogDebug(...) vlog(LOG_DEBUG, __VA_ARGS__) - -void logSetQuiet(uint8_t enable); -void logSetLevel(int level); -void logSetSyslog(int options, int facility); -int logSetPipe(char *pipe_file); -int logSetFile(char *file); -void logClose(void); - -void vlog(int level, const char *fmt, va_list args); -void logEmergency(const char *fmt, ...) __attribute__((format(printf,1,2))); -void logAlert(const char *fmt, ...) __attribute__((format(printf,1,2))); -void logCritical(const char *fmt, ...) __attribute__((format(printf,1,2))); -void logError(const char *fmt, ...) __attribute__((format(printf,1,2))); -void logWarning(const char *fmt, ...) __attribute__((format(printf,1,2))); -void logNotice(const char *fmt, ...) __attribute__((format(printf,1,2))); -void logInfo(const char *fmt, ...) __attribute__((format(printf,1,2))); -void logDebug(const char *fmt, ...) __attribute__((format(printf,1,2))); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/noniso.cpp b/lib/MySensors/hal/architecture/Linux/drivers/core/noniso.cpp deleted file mode 100644 index f751bb31..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/noniso.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - noniso.cpp - replacements for non-ISO functions used by Arduino core - Copyright © 2016 Ivan Grokhotkov - - 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. - - Modified August 2016 by Marcelo Aquino for MySensors use -*/ - -#include -#include -#include -#include -#include -#include -#include "stdlib_noniso.h" - -char* utoa(unsigned value, char* result, int base) -{ - if(base < 2 || base > 16) { - *result = 0; - return result; - } - - char* out = result; - unsigned quotient = value; - - do { - const unsigned tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); - - reverse(result, out); - *out = 0; - return result; -} - -char* itoa(int value, char* result, int base) -{ - if(base < 2 || base > 16) { - *result = 0; - return result; - } - - char* out = result; - int quotient = abs(value); - - do { - const int tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); - - // Apply negative sign - if(value < 0) { - *out++ = '-'; - } - - reverse(result, out); - *out = 0; - return result; -} - -int atoi(const char* s) -{ - return (int) atol(s); -} - -long atol(const char* s) -{ - char * tmp; - return strtol(s, &tmp, 10); -} - -double atof(const char* s) -{ - char * tmp; - return strtod(s, &tmp); -} - -void reverse(char* begin, char* end) -{ - char *is = begin; - char *ie = end - 1; - while(is < ie) { - char tmp = *ie; - *ie = *is; - *is = tmp; - ++is; - --ie; - } -} - -char* ltoa(long value, char* result, int base) -{ - if(base < 2 || base > 16) { - *result = 0; - return result; - } - - char* out = result; - long quotient = abs(value); - - do { - const long tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); - - // Apply negative sign - if(value < 0) { - *out++ = '-'; - } - - reverse(result, out); - *out = 0; - return result; -} - -char* ultoa(unsigned long value, char* result, int base) -{ - if(base < 2 || base > 16) { - *result = 0; - return result; - } - - char* out = result; - unsigned long quotient = value; - - do { - const unsigned long tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); - - reverse(result, out); - *out = 0; - return result; -} - -char* dtostrf (double val, signed char width, unsigned char prec, char *s) -{ - sprintf(s,"%*.*f", width, prec, val); - return s; -} diff --git a/lib/MySensors/hal/architecture/Linux/drivers/core/stdlib_noniso.h b/lib/MySensors/hal/architecture/Linux/drivers/core/stdlib_noniso.h deleted file mode 100644 index ddbb920e..00000000 --- a/lib/MySensors/hal/architecture/Linux/drivers/core/stdlib_noniso.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - stdlib_noniso.h - nonstandard (but usefull) conversion functions - - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - 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 STDLIB_NONISO_H -#define STDLIB_NONISO_H - -#ifdef __cplusplus -extern "C" { -#endif - -int atoi(const char *s); - -long atol(const char* s); - -double atof(const char* s); - -char* itoa (int val, char *s, int radix); - -char* ltoa (long val, char *s, int radix); - -char* utoa (unsigned int val, char *s, int radix); - -char* ultoa (unsigned long val, char *s, int radix); - -char* dtostrf (double val, signed char width, unsigned char prec, char *s); - -void reverse(char* begin, char* end); - -#ifdef __cplusplus -} // extern "C" -#endif - - -#endif diff --git a/lib/MySensors/hal/architecture/MyHwHAL.cpp b/lib/MySensors/hal/architecture/MyHwHAL.cpp deleted file mode 100644 index 19edd9ed..00000000 --- a/lib/MySensors/hal/architecture/MyHwHAL.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHwHAL.h" - -void hwDebugPrint(const char *fmt, ...) -{ -#ifndef MY_DISABLED_SERIAL -#if !defined(__linux__) - char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; -#ifdef MY_GATEWAY_SERIAL - // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) - snprintf_P(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%" PRIu8 ";0;%" PRIu8 ";"), C_INTERNAL, - I_LOG_MESSAGE); - MY_DEBUGDEVICE.print(fmtBuffer); -#endif - // prepend timestamp - MY_DEBUGDEVICE.print(hwMillis()); - MY_DEBUGDEVICE.print(" "); - va_list args; - va_start(args, fmt); - vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); -#ifdef MY_GATEWAY_SERIAL - // Truncate message if this is gateway node - fmtBuffer[sizeof(fmtBuffer) - 2] = '\n'; - fmtBuffer[sizeof(fmtBuffer) - 1] = '\0'; -#endif - va_end(args); - MY_DEBUGDEVICE.print(fmtBuffer); - MY_DEBUGDEVICE.flush(); -#else - va_list args; - va_start(args, fmt); - vlogDebug(fmt, args); - va_end(args); -#endif -#else - (void)fmt; -#endif -} - -#if defined(DEBUG_OUTPUT_ENABLED) -static char hwDebugPrintStr[65]; -static void hwDebugBuf2Str(const uint8_t *buf, size_t sz) -{ - if (sz > 32) { - sz = 32; //clamp to 32 bytes - } - for (uint8_t i = 0; i < sz; i++) { - hwDebugPrintStr[i * 2] = convertI2H(buf[i] >> 4); - hwDebugPrintStr[(i * 2) + 1] = convertI2H(buf[i]); - } - hwDebugPrintStr[sz * 2] = '\0'; -} -#endif diff --git a/lib/MySensors/hal/architecture/MyHwHAL.h b/lib/MySensors/hal/architecture/MyHwHAL.h deleted file mode 100644 index f7e407a6..00000000 --- a/lib/MySensors/hal/architecture/MyHwHAL.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -/** -* @file MyHwHAL.h -* -* MySensors hardware abstraction layer -*/ - -#ifndef MyHwHAL_h -#define MyHwHAL_h - -/** -* @def INVALID_INTERRUPT_NUM -* @brief Invalid interrupt -*/ -#define INVALID_INTERRUPT_NUM (0xFFu) - -/** -* @def MY_HWID_PADDING_BYTE -* @brief HwID padding byte -*/ -#define MY_HWID_PADDING_BYTE (0xAAu) - -/** -* @def IRQ_HANDLER_ATTR -* @brief ESP8266/ESP32 IRQ handlers need to be stored in IRAM -*/ -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#define IRQ_HANDLER_ATTR ICACHE_RAM_ATTR -#else -#define IRQ_HANDLER_ATTR -#endif - -// Implement these as functions or macros -/* -#define hwInit() MY_SERIALDEVICE.begin(BAUD_RATE) -#define hwWatchdogReset() wdt_reset() -#define hwReboot() wdt_enable(WDTO_15MS); while (1) -#define hwMillis() millis() - -#define hwDigitalWrite(__pin, __value) -#define hwDigitalRead(__pin) -#define hwPinMode(__pin, __value) - -void hwReadConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfig(const int addr, uint8_t value); -uint8_t hwReadConfig(const int addr); -*/ - -/** - * @def MY_HW_HAS_GETENTROPY - * @brief Define this, if hwGetentropy is implemented - * - * ssize_t hwGetentropy(void *__buffer, size_t __length); - */ -//#define MY_HW_HAS_GETENTROPY - -/// @brief unique ID -typedef uint8_t unique_id_t[16]; - -/** - * Sleep for a defined time, using minimum power. - * @param ms Time to sleep, in [ms]. - * @return MY_WAKE_UP_BY_TIMER. - */ -int8_t hwSleep(uint32_t ms); - -/** - * Sleep for a defined time, using minimum power, or until woken by interrupt. - * @param interrupt Interrupt number, which can wake the mcu from sleep. - * @param mode Interrupt mode, as passed to attachInterrupt. - * @param ms Time to sleep, in [ms]. - * @return MY_WAKE_UP_BY_TIMER when woken by timer, or interrupt number when woken by interrupt. - */ -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms); - -/** - * Sleep for a defined time, using minimum power, or until woken by one of the interrupts. - * @param interrupt1 Interrupt1 number, which can wake the mcu from sleep. - * @param mode1 Interrupt1 mode, as passed to attachInterrupt. - * @param interrupt2 Interrupt2 number, which can wake the mcu from sleep. - * @param mode2 Interrupt2 mode, as passed to attachInterrupt. - * @param ms Time to sleep, in [ms]. - * @return MY_WAKE_UP_BY_TIMER when woken by timer, or interrupt number when woken by interrupt. - */ -int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, - uint32_t ms); - -/** -* Retrieve unique hardware ID -* @param uniqueID unique ID -* @return True if unique ID successfully retrieved -*/ -bool hwUniqueID(unique_id_t *uniqueID); - -/** - * CPU voltage - * @return CPU voltage in mV - */ -uint16_t hwCPUVoltage(void); - -/** - * CPU frequency - * @return CPU frequency in 1/10Mhz - */ -uint16_t hwCPUFrequency(void); - -/** - * CPU temperature (if available) - * Adjust calibration parameters via MY__TEMPERATURE_OFFSET and MY__TEMPERATURE_GAIN - * @return CPU temperature in °C, -127 if not available - */ -int8_t hwCPUTemperature(void); - -/** - * Report free memory (if function available) - * @return free memory in bytes - */ -uint16_t hwFreeMem(void); - -#if defined(DEBUG_OUTPUT_ENABLED) -/** - * Debug print - * @param fmt - */ -void hwDebugPrint(const char *fmt, ...); -/** - * Convert buffer to hex string - * @param buf - * @param sz - */ -static void hwDebugBuf2Str(const uint8_t *buf, size_t sz) __attribute__((unused)); -#endif - -/** - * @def MY_CRITICAL_SECTION - * @brief Creates a block of code that is guaranteed to be executed atomically. - * Upon entering the block all interrupts are disabled, and re-enabled upon - * exiting the block from any exit path. - * A typical example that requires atomic access is a 16 (or more) bit variable - * that is shared between the main execution path and an ISR, on an 8-bit - * platform (e.g AVR): - * @code - * volatile uint16_t val = 0; - * - * void interrupHandler() - * { - * val = ~val; - * } - * - * void loop() - * { - * uint16_t copy_val; - * MY_CRITICAL_SECTION - * { - * copy_val = val; - * } - * } - * @endcode - * All code within the MY_CRITICAL_SECTION block will be protected from being - * interrupted during execution. - */ -#ifdef DOXYGEN -#define MY_CRITICAL_SECTION -#define MY_HW_HAS_GETENTROPY -#endif /* DOXYGEN */ - -#endif // #ifdef MyHw_h diff --git a/lib/MySensors/hal/architecture/NRF5/MyHwNRF5.cpp b/lib/MySensors/hal/architecture/NRF5/MyHwNRF5.cpp deleted file mode 100644 index 3b5dff39..00000000 --- a/lib/MySensors/hal/architecture/NRF5/MyHwNRF5.cpp +++ /dev/null @@ -1,533 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of - * the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Copyright (C) 2017 Frank Holtz - * Full contributor list: - * https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHwNRF5.h" - -volatile uint8_t _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu. -volatile uint8_t _wakeUp1Interrupt = - INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback. -volatile uint8_t _wakeUp2Interrupt = - INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback. - -void wakeUp1(void) // place to send the interrupts -{ - _wokeUpByInterrupt = _wakeUp1Interrupt; -} -void wakeUp2(void) // place to send the second interrupts -{ - _wokeUpByInterrupt = _wakeUp2Interrupt; -} - -void hwReadConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *dst = static_cast(buf); - const int offs = reinterpret_cast(addr); - (void)NVRAM.read_block(dst, offs, length); -} - -void hwWriteConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *src = static_cast(buf); - const int offs = reinterpret_cast(addr); - (void)NVRAM.write_block(src, offs, length); -} - -uint8_t hwReadConfig(const int addr) -{ - return NVRAM.read(addr); -} - -void hwWriteConfig(const int addr, uint8_t value) -{ - (void)NVRAM.write(addr, value); -} - -bool hwInit(void) -{ -#ifdef MY_LOCK_MCU -#ifdef NRF51 - // Lock MCU - if((uint32_t)((NRF_UICR->RBPCONF & UICR_RBPCONF_PALL_Msk) >> UICR_RBPCONF_PALL_Pos) != - UICR_RBPCONF_PALL_Enabled) { - Flash.write((uint32_t *)&NRF_UICR->RBPCONF, (NRF_UICR->RBPCONF & ~UICR_RBPCONF_PALL_Msk)); - hwReboot(); - } -#else - // Lock MCU - if((uint32_t)((NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk) >> UICR_APPROTECT_PALL_Pos) != - UICR_APPROTECT_PALL_Enabled) { - Flash.write((uint32_t *)&NRF_UICR->APPROTECT, (NRF_UICR->APPROTECT & ~UICR_APPROTECT_PALL_Msk)); - hwReboot(); - } -#endif -#endif - -#if defined(NRF51) && defined(CONFIG_ENABLE_PINRESET) - // Enabling reset for NRF51 isn't handled by arduino-nrf5. Enable it, if requested. - NRF_POWER->RESET = POWER_RESET_RESET_Enabled; - NRF_POWER->RAMON |= (POWER_RAMON_ONRAM0_RAM0On << POWER_RAMON_ONRAM0_Pos) | - (POWER_RAMON_ONRAM1_RAM1On << POWER_RAMON_ONRAM1_Pos); -#endif - - // Clock is manged by sleep modes. Radio depends on HFCLK. - // Force to start HFCLK - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - NRF_CLOCK->TASKS_HFCLKSTART = 1; - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) - ; - - // Enable low latency sleep mode - NRF_POWER->TASKS_CONSTLAT = 1; - - // Enable cache on >= NRF52 -#ifndef NRF51 - NRF_NVMC->ICACHECNF = NVMC_ICACHECNF_CACHEEN_Msk; -#endif - - // Suspend UART - NRF_UART0->TASKS_STOPRX = 1; - NRF_UART0->TASKS_STOPTX = 1; - NRF_UART0->TASKS_SUSPEND = 1; - -#ifdef MY_DISABLED_SERIAL - // Disable UART, when not configured -#ifdef NRF51 - NRF_UART0->POWER = 0; -#endif -#else - // Configure UART - MY_SERIALDEVICE.begin(MY_BAUD_RATE); -#if defined(MY_GATEWAY_SERIAL) - while (!MY_SERIALDEVICE) { - } -#endif -#endif - - return true; -} - -static nrf_ecb_t hwRngData; -static int8_t hwRndDataReadPos = -1; - -void hwRandomNumberInit(void) -{ - // Start HWRNG -#ifdef NRF51 - NRF_RNG->POWER = 1; -#endif - // Enable "more random" numbers - NRF_RNG->CONFIG = RNG_CONFIG_DERCEN_Enabled << RNG_CONFIG_DERCEN_Pos; - NRF_RNG->TASKS_START = 1; - NRF_RNG->EVENTS_VALRDY = 0; - - uint32_t seed = 0; - for (uint8_t i = 0; i < 4; i++) { - // Wait for an random number - while (NRF_RNG->EVENTS_VALRDY == 0) { - yield(); - } - seed = (seed << 8) | (uint32_t)NRF_RNG->VALUE; - NRF_RNG->EVENTS_VALRDY = 0; - } - randomSeed(seed); - - // Fill ESB data structure for fast random data generation - uint8_t *ecbstruct = (uint8_t *)&hwRngData; - for (uint8_t i = 0; iEVENTS_VALRDY == 0) { - yield(); - } - *(ecbstruct + i) = NRF_RNG->VALUE; - NRF_RNG->EVENTS_VALRDY = 0; - } - hwRndDataReadPos = 0; - - // Stop HWRNG - NRF_RNG->TASKS_STOP = 1; -#ifdef NRF51 - NRF_RNG->POWER = 0; -#endif -} - -ssize_t hwGetentropy(void *__buffer, size_t __length) -{ - if (hwRndDataReadPos<0) { - // Not initialized - hwRandomNumberInit(); - } - - // cut length if > 256 - if (__length > 256) { - __length = 256; - } - uint8_t *dst = (uint8_t *)__buffer; - - // Start random number generator - for (size_t i = 0; i < __length; i++) { - dst[i] = hwRngData.ciphertext[hwRndDataReadPos & 0xfu]; - MY_CRITICAL_SECTION { - if (hwRndDataReadPos >= ((int8_t)sizeof(hwRngData.ciphertext)-1)) - { - // Retry until no error - bool need_data = true; - while (need_data) { - // Stop if another task is running - NRF_ECB->TASKS_STOPECB = 1; - NRF_ECB->EVENTS_ERRORECB = 0; - NRF_ECB->EVENTS_ENDECB = 0; - uint32_t ptrbackup = NRF_ECB->ECBDATAPTR; - NRF_ECB->ECBDATAPTR = (uint32_t)&hwRngData; - NRF_ECB->TASKS_STARTECB = 1; - while (!NRF_ECB->EVENTS_ENDECB); - NRF_ECB->ECBDATAPTR = ptrbackup; - if (NRF_ECB->EVENTS_ERRORECB == 0) { - need_data = false; - } - } - hwRndDataReadPos=0; - for (uint8_t pos = 0; pos < sizeof(hwRngData.ciphertext); pos++) { - hwRngData.cleartext[pos] ^= hwRngData.ciphertext[pos]; - } - } else - { - hwRndDataReadPos++; - } - } - } - - return __length; -} - -void hwWatchdogReset(void) -{ - NRF_WDT->RR[0] = WDT_RR_RR_Reload; -} - -void hwReboot(void) -{ - NVIC_SystemReset(); - while (true) - ; -} - -static volatile bool nrf5_rtc_event_triggered; -static volatile bool nrf5_pwr_hfclk; - -void hwSleepPrepare(uint32_t ms) -{ - // Enable low power sleep mode - NRF_POWER->TASKS_LOWPWR = 1; - - // Reset RTC trigger flag - nrf5_rtc_event_triggered = false; - - if (ms > 0) { - // Configure RTC -#ifdef NRF51 - MY_HW_RTC->POWER = 1; -#endif - // Reset RTC - MY_HW_RTC->TASKS_CLEAR = 1; - - // Calculate sleep time and prescaler - if (ms<512000) { - // prescaler 0, 30.517 μs resolution -> max 512 s sleep - MY_HW_RTC->PRESCALER = 0; - // Set compare register to 1/30.517 µs to guarantee event triggering - // A minimum of 2 ticks must be guaranteed - // (1000/32768)<<12 == 125 - MY_HW_RTC->CC[0] = max(((ms << 12) / 125), 2); - } else { - // 8 Hz -> max 582.542 hours sleep. - MY_HW_RTC->PRESCALER = 4095; - // Set compare register to 1/125ms - // A minimum of 2 ticks must be guaranteed - MY_HW_RTC->CC[0] = max((ms / 125), 2); - } - - MY_HW_RTC->INTENSET = RTC_INTENSET_COMPARE0_Msk; - MY_HW_RTC->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; - MY_HW_RTC->EVENTS_COMPARE[0] = 0; - MY_HW_RTC->TASKS_START = 1; - NVIC_SetPriority(MY_HW_RTC_IRQN, 15); - NVIC_ClearPendingIRQ(MY_HW_RTC_IRQN); - NVIC_EnableIRQ(MY_HW_RTC_IRQN); - } else { - NRF_RTC1->TASKS_STOP = 1; - } - - // Stop HFCLK - nrf5_pwr_hfclk = NRF_CLOCK->EVENTS_HFCLKSTARTED; - NRF_CLOCK->TASKS_HFCLKSTOP = 1; - - // Idle serial device -#ifndef MY_DISABLED_SERIAL - NRF_UART0->TASKS_STOPRX = 1; - NRF_UART0->TASKS_STOPTX = 1; - NRF_UART0->TASKS_SUSPEND = 1; -#endif - - // Clear NVRAM log, if needed and a time frame of 4 seconds available - if (ms > 40000) { - // preserve some bytes for writing to NVRAM - NVRAM.clean_up(32); - } -} - -void hwSleepEnd(uint32_t ms) -{ - // Start HFCLK - if (nrf5_pwr_hfclk) { - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - NRF_CLOCK->TASKS_HFCLKSTART = 1; - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) - ; - // Enable low latency sleep mode - NRF_POWER->TASKS_CONSTLAT = 1; - } - - if (ms > 0) { - // Stop RTC -#ifdef NRF51 - MY_HW_RTC->POWER = 0; -#endif - MY_HW_RTC->INTENCLR = RTC_INTENSET_COMPARE0_Msk; - MY_HW_RTC->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; - MY_HW_RTC->TASKS_STOP = 1; - NVIC_DisableIRQ(MY_HW_RTC_IRQN); - } else { - // Start Arduino RTC for millis() - NRF_RTC1->TASKS_START = 1; - } - - // Start serial device -#ifndef MY_DISABLED_SERIAL - NRF_UART0->TASKS_STARTRX = 1; - NRF_UART0->TASKS_STARTTX = 1; -#endif -} - -// Halt CPU until next interrupt event -inline void hwWaitForInterrupt(void) -{ - __DSB(); - __WFI(); -} - -// Sleep in System ON mode -inline void hwSleep(void) -{ - __WFE(); - __SEV(); - __WFE(); -} - -int8_t hwSleep(uint32_t ms) -{ - hwSleepPrepare(ms); - while (nrf5_rtc_event_triggered == false) { - hwSleep(); - } - hwSleepEnd(ms); - return MY_WAKE_UP_BY_TIMER; -} - -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms) -{ - return hwSleep(interrupt, mode, INVALID_INTERRUPT_NUM, 0u, ms); -} - -int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, - uint8_t mode2, uint32_t ms) -{ - // Disable interrupts until going to sleep, otherwise interrupts occurring - // between attachInterrupt() - // and sleep might cause the MCU to not wakeup from sleep as interrupt has - // already be handled! - MY_CRITICAL_SECTION { - // attach interrupts - _wakeUp1Interrupt = interrupt1; - _wakeUp2Interrupt = interrupt2; - - if (interrupt1 != INVALID_INTERRUPT_NUM) - { - attachInterrupt(interrupt1, wakeUp1, mode1); - } - if (interrupt2 != INVALID_INTERRUPT_NUM) - { - attachInterrupt(interrupt2, wakeUp2, mode2); - } - - // Reset attribute - _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; - } - - // Prepare Timer and Hardware - hwSleepPrepare(ms); - - // Sleep until timeout or interrupt - while ((nrf5_rtc_event_triggered == false) and - (_wokeUpByInterrupt == INVALID_INTERRUPT_NUM)) { - hwSleep(); - } - - // Assure any interrupts attached, will get detached when they did not occur. - if (interrupt1 != INVALID_INTERRUPT_NUM) { - detachInterrupt(interrupt1); - } - if (interrupt2 != INVALID_INTERRUPT_NUM) { - detachInterrupt(interrupt2); - } - - // Wake up Hardware - hwSleepEnd(ms); - - // Return what woke the mcu. - int8_t ret = - MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up - if (_wokeUpByInterrupt != INVALID_INTERRUPT_NUM) { - ret = static_cast(_wokeUpByInterrupt); - } - // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. - _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; - - return ret; -} - -extern "C" { - // RTC interrupt handler - void MY_HW_RTC_IRQ_HANDLER(void) - { - if (MY_HW_RTC->EVENTS_COMPARE[0] > 0) { - nrf5_rtc_event_triggered = true; - - NRF_RESET_EVENT(MY_HW_RTC->EVENTS_COMPARE[0]); - } - } -} - -bool hwUniqueID(unique_id_t *uniqueID) -{ - uint32_t *buffer = (uint32_t *)uniqueID; - buffer[0] = NRF_FICR->DEVICEID[0]; - buffer[1] = NRF_FICR->DEVICEID[1]; - buffer[2] = NRF_FICR->DEVICEADDR[0]; - buffer[3] = NRF_FICR->DEVICEADDR[1]; - return true; -} - -uint16_t hwCPUVoltage(void) -{ - // VDD is prescaled 1/3 and compared with the internal 1.2V reference -#if defined(NRF_ADC) - // NRF51: - // Sampling is done with lowest resolution to minimize the time - // 20uS@260uA - - // Concurrent resource: disable - uint32_t lpcomp_enabled = NRF_LPCOMP->ENABLE; - NRF_LPCOMP->ENABLE = 0; - - // Enable and configure ADC - NRF_ADC->ENABLE = 1; - NRF_ADC->CONFIG = (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos) | - (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) | - (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) | - (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | - (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos); - NRF_ADC->EVENTS_END = 0; - NRF_ADC->TASKS_START = 1; - while(!NRF_ADC->EVENTS_END); - NRF_ADC->EVENTS_END = 0; - int32_t sample = (int32_t)NRF_ADC->RESULT; - NRF_ADC->TASKS_STOP = 1; - NRF_ADC->ENABLE = 0; - - // Restore LPCOMP state - NRF_LPCOMP->ENABLE = lpcomp_enabled; - - return (sample*3600)/255; - -#elif defined(NRF_SAADC) - // NRF52: - // Sampling time 3uS@700uA - int32_t sample; - NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos; - NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_8bit << SAADC_RESOLUTION_VAL_Pos; - NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD << SAADC_CH_PSELP_PSELP_Pos; - NRF_SAADC->CH[0].CONFIG = (SAADC_CH_CONFIG_BURST_Disabled << SAADC_CH_CONFIG_BURST_Pos) | - (SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos) | - (SAADC_CH_CONFIG_TACQ_3us << SAADC_CH_CONFIG_TACQ_Pos) | - (SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) | - (SAADC_CH_CONFIG_GAIN_Gain1_6 << SAADC_CH_CONFIG_GAIN_Pos) | - (SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos) | - (SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos); - NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Bypass << SAADC_OVERSAMPLE_OVERSAMPLE_Pos; - NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos; - NRF_SAADC->RESULT.MAXCNT = 1; - NRF_SAADC->RESULT.PTR = (uint32_t)&sample; - - NRF_SAADC->EVENTS_STARTED = 0; - NRF_SAADC->TASKS_START = 1; - while (!NRF_SAADC->EVENTS_STARTED); - NRF_SAADC->EVENTS_STARTED = 0; - - NRF_SAADC->EVENTS_END = 0; - NRF_SAADC->TASKS_SAMPLE = 1; - while (!NRF_SAADC->EVENTS_END); - NRF_SAADC->EVENTS_END = 0; - - NRF_SAADC->EVENTS_STOPPED = 0; - NRF_SAADC->TASKS_STOP = 1; - while (!NRF_SAADC->EVENTS_STOPPED); - NRF_SAADC->EVENTS_STOPPED = 1; - - NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Disabled << SAADC_ENABLE_ENABLE_Pos); - - return (sample*3600)/255; -#else - // unknown MCU - return 0; -#endif -} - -uint16_t hwCPUFrequency(void) -{ -#if defined(VARIANT_MCK) - return (VARIANT_MCK) / 100000UL; -#elif defined(F_CPU) - return (F_CPU) / 100000UL; -#else - return 160; -#endif -} - -int8_t hwCPUTemperature(void) -{ - return -127; // not implemented yet -} - -uint16_t hwFreeMem(void) -{ - // TODO: Not supported! - return FUNCTION_NOT_SUPPORTED; -} diff --git a/lib/MySensors/hal/architecture/NRF5/MyHwNRF5.h b/lib/MySensors/hal/architecture/NRF5/MyHwNRF5.h deleted file mode 100644 index 94b46ff2..00000000 --- a/lib/MySensors/hal/architecture/NRF5/MyHwNRF5.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of - * the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Copyright (C) 2017 Frank Holtz - * Full contributor list: - * https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ -#ifndef MyHwNRF5_h -#define MyHwNRF5_h - -#ifdef __cplusplus -#include -#endif - -#define CRYPTO_LITTLE_ENDIAN - -#ifndef MY_SERIALDEVICE -#define MY_SERIALDEVICE Serial -#endif - -#ifndef MY_DEBUGDEVICE -#define MY_DEBUGDEVICE MY_SERIALDEVICE -#endif - -// Define NRF5_SOFTDEVICE when SoftDevice found -#if defined(S110) || defined(S130) || defined(S132) || defined(S140) -#ifndef SOFTDEVICE_PRESENT -#define SOFTDEVICE_PRESENT -#endif -#endif - -// Define ARDUINO_ARCH_NRF5, if not defined -#ifndef ARDUINO_ARCH_NRF5 -#define ARDUINO_ARCH_NRF5 -#endif - -#include "hal/architecture/NRF5/drivers/nrf5_wiring_digital.c" -#include "hal/architecture/NRF5/drivers/wdt.h" -#include "hal/architecture/NRF5/drivers/nrf_temp.h" -#include "drivers/NVM/NVRAM.cpp" -#include "drivers/NVM/VirtualPage.cpp" -#include -#include -#include - -// mapping -#ifndef strncpy_P -#define strncpy_P strncpy -#endif -#ifndef snprintf_P -#define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__) -#endif -#ifndef vsnprintf_P -#define vsnprintf_P vsnprintf -#endif -#ifndef printf_P -#define printf_P printf -#endif - -// redefine 8 bit types of inttypes.h until fix of https://github.com/sandeepmistry/arduino-nRF5/issues/197 -#undef PRId8 -#undef PRIi8 -#undef PRIo8 -#undef PRIu8 -#undef PRIx8 -#undef PRIX8 -#undef PRIdLEAST8 -#undef PRIiLEAST8 -#undef PRIoLEAST8 -#undef PRIuLEAST8 -#undef PRIxLEAST8 -#undef PRIXLEAST8 -#undef PRIdFAST8 -#undef PRIiFAST8 -#undef PRIoFAST8 -#undef PRIuFAST8 -#undef PRIxFAST8 -#undef PRIXFAST8 -#define PRId8 "hd" -#define PRIi8 "hi" -#define PRIo8 "ho" -#define PRIu8 "hu" -#define PRIx8 "hx" -#define PRIX8 "hX" -#define PRIdLEAST8 "hd" -#define PRIiLEAST8 "hi" -#define PRIoLEAST8 "ho" -#define PRIuLEAST8 "hu" -#define PRIxLEAST8 "hx" -#define PRIXLEAST8 "hX" -#define PRIdFAST8 "hd" -#define PRIiFAST8 "hi" -#define PRIoFAST8 "ho" -#define PRIuFAST8 "hu" -#define PRIxFAST8 "hx" -#define PRIXFAST8 "hX" - -// Define these as macros to save valuable space -#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value) -#define hwDigitalRead(__pin) digitalRead(__pin) -#define hwPinMode(__pin, __value) nrf5_pinMode(__pin, __value) -#define hwMillis() millis() -// TODO: Can nrf5 determine time slept? -#define hwGetSleepRemaining() (0ul) - -bool hwInit(void); -void hwWatchdogReset(void); -void hwReboot(void); -void hwReadConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfig(const int addr, uint8_t value); -uint8_t hwReadConfig(const int addr); -void hwRandomNumberInit(void); -ssize_t hwGetentropy(void *__buffer, size_t __length); -#define MY_HW_HAS_GETENTROPY - -// SOFTSPI -#ifdef MY_SOFTSPI -#error Soft SPI is not available on this architecture! -#endif -#define hwSPI SPI //!< hwSPI - - -/** - * Disable all interrupts. - * Helper function for MY_CRITICAL_SECTION. - */ -static __inline__ uint8_t __disableIntsRetVal(void) -{ - __disable_irq(); - return 1; -} - -/** - * Restore priority mask register. - * Helper function for MY_CRITICAL_SECTION. - */ -static __inline__ void __priMaskRestore(const uint32_t *priMask) -{ - __set_PRIMASK(*priMask); -} - -/** - * Reset events and read back on nRF52 - * http://infocenter.nordicsemi.com/pdf/nRF52_Series_Migration_v1.0.pdf - */ -#if __CORTEX_M == 0x04 -#define NRF_RESET_EVENT(event) \ - event = 0; \ - (void)event -#else -#define NRF_RESET_EVENT(event) event = 0 -#endif -/** - * RTC to use for hwSleep - * RTC1 is used by arduino-nRF5 - * RTC2 is used on nRF52 - * RTC0 is used on nRF51. This conflicts with SoftDevice! - */ -#ifdef NRF_RTC2 -#define MY_HW_RTC NRF_RTC2 -#define MY_HW_RTC_IRQ_HANDLER RTC2_IRQHandler -#define MY_HW_RTC_IRQN RTC2_IRQn -#else -#define MY_HW_RTC NRF_RTC0 -#define MY_HW_RTC_IRQ_HANDLER RTC0_IRQHandler -#define MY_HW_RTC_IRQN RTC0_IRQn -#endif - -/** Datastructure for AES ECB unit - */ -typedef struct { - /** AES Key - */ - uint8_t key[16]; - /** Unencrypted data - */ - uint8_t cleartext[16]; - /** Encrypted data - */ - uint8_t ciphertext[16]; -} nrf_ecb_t; - -#if !defined(DOXYGEN) && !defined(CPPCHECK) -#define MY_CRITICAL_SECTION \ - for (uint32_t __savePriMask \ - __attribute__((__cleanup__(__priMaskRestore))) = __get_PRIMASK(), \ - __ToDo = __disableIntsRetVal(); \ - __ToDo; __ToDo = 0) -#else -#define MY_CRITICAL_SECTION -#endif /* DOXYGEN || CPPCHECK */ - -#endif // #ifndef MyHwNRF5_h diff --git a/lib/MySensors/hal/architecture/NRF5/MyMainNRF5.cpp b/lib/MySensors/hal/architecture/NRF5/MyMainNRF5.cpp deleted file mode 100644 index dd02675f..00000000 --- a/lib/MySensors/hal/architecture/NRF5/MyMainNRF5.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -// Initialize library and handle sketch functions like we want to - -int main(void) -{ - init(); -#if defined(USBCON) - USBDevice.attach(); -#endif - _begin(); // Startup MySensors library - for(;;) { - _process(); // Process incoming data - if (loop) { - loop(); // Call sketch loop - } - if (serialEventRun) { - serialEventRun(); - } - } - return 0; -} diff --git a/lib/MySensors/hal/architecture/NRF5/drivers/Flash.cpp b/lib/MySensors/hal/architecture/NRF5/drivers/Flash.cpp deleted file mode 100644 index 0e7965c0..00000000 --- a/lib/MySensors/hal/architecture/NRF5/drivers/Flash.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - Flash.cpp - Flash library - Original Copyright (c) 2017 Frank Holtz. All right reserved. - - 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 "drivers/NVM/Flash.h" -#include - -FlashClass Flash; - -uint32_t FlashClass::page_size() const -{ - return (size_t)NRF_FICR->CODEPAGESIZE; -} - -uint8_t FlashClass::page_size_bits() const -{ -#if defined(NRF51) - return 10; -#elif defined(NRF52) - return 12; -#endif -} - -uint32_t FlashClass::page_count() const -{ - return (uint32_t)NRF_FICR->CODESIZE; -} - -uint32_t FlashClass::specified_erase_cycles() const -{ - return FLASH_ERASE_CYCLES; -} - -uint32_t *FlashClass::page_address(size_t page) -{ - return (uint32_t *)(page << page_size_bits()); -} - -uint32_t *FlashClass::top_app_page_address() -{ -#if !defined(MCUBOOT_PRESENT) - // Bootcode at the top of the flash memory? - // https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v12.0.0%2Flib_bootloader.html - if (NRF_UICR->NRFFW[0]<0xFFFFFFFF) { - // Return pointer calculated by SoftDevice/bootloader - return (uint32_t *)NRF_UICR->NRFFW[0]; - } -#endif - - // Return flash length - return (uint32_t *)(Flash.page_count() << Flash.page_size_bits()); -} - -void FlashClass::erase(uint32_t *address, size_t size) -{ - size_t end_address = (size_t)address + size; - - // align address - address = - (uint32_t *)((size_t)address & (size_t)((size_t)(~0) - FLASH_PAGE_SIZE)); - - // Wrong parameters? - if ((size_t)address >= end_address) { - return; - } - - // get old nvm controller state - uint32_t old_config = NRF_NVMC->CONFIG; - - // Enable erasing flash - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos; - - // Erase page(s) - while ((size_t)address < end_address) { - wait_for_ready(); - // Erase one 1k/4k page - NRF_NVMC->ERASEPAGE = (size_t)(address); - address = (uint32_t *)((size_t)address + FLASH_PAGE_SIZE); - } - - // Disable erasing - wait_for_ready(); - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; - - // Restore old state - wait_for_ready(); - NRF_NVMC->CONFIG = old_config; - - // Go back if controller is ready - wait_for_ready(); -} - -void FlashClass::erase_all() -{ - // Enable erasing flash - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos; - wait_for_ready(); - - // Erase Flash and UICR - NRF_NVMC->ERASEALL = 1; - wait_for_ready(); - - // Disable erasing - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; - wait_for_ready(); -} - -void FlashClass::write(uint32_t *address, uint32_t value) -{ - // Compare word - if (*address != value) { - // Enable write - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; - wait_for_ready(); - // Write word - *address = value; - // Disable write - wait_for_ready(); - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; - wait_for_ready(); - } -} - -void FlashClass::write_block(uint32_t *dst_address, uint32_t *src_address, - uint16_t word_count) -{ - // Enable write - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; - wait_for_ready(); - - while (word_count > 0) { - // cppcheck-suppress duplicateConditionalAssign - if (*dst_address != *src_address) { - *dst_address = *src_address; - } - word_count--; - dst_address++; - src_address++; - } - - // Disable write - wait_for_ready(); - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; - wait_for_ready(); -} - -void FlashClass::wait_for_ready() -{ - while (NRF_NVMC->READY == NVMC_READY_READY_Busy) { - }; -} diff --git a/lib/MySensors/hal/architecture/NRF5/drivers/nrf5_wiring_constants.h b/lib/MySensors/hal/architecture/NRF5/drivers/nrf5_wiring_constants.h deleted file mode 100644 index 0e078854..00000000 --- a/lib/MySensors/hal/architecture/NRF5/drivers/nrf5_wiring_constants.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * nRF5 output modes - */ -// Standard 0, Standard 1 -#ifndef OUTPUT_S0S1 -#define OUTPUT_S0S1 (0x10) -#endif - -// High Drive 0, Standard 1 -#ifndef OUTPUT_H0S1 -#define OUTPUT_H0S1 (0x11) -#endif - -// Standard 0, High Drive 1 -#ifndef OUTPUT_S0H1 -#define OUTPUT_S0H1 (0x12) -#endif - -// High Drive both -#ifndef OUTPUT_H0H1 -#define OUTPUT_H0H1 (0x13) -#endif - -// Disconnected 0, Standard 1 -#ifndef OUTPUT_D0S1 -#define OUTPUT_D0S1 (0x14) -#endif - -// Disconnected 0, High Drive 1 -#ifndef OUTPUT_D0H1 -#define OUTPUT_D0H1 (0x15) -#endif - -// Standard 0, Disconnected 1 -#ifndef OUTPUT_S0D1 -#define OUTPUT_S0D1 (0x16) -#endif - -// High Drive 0, Disconnected 1 -#ifndef OUTPUT_H0D1 -#define OUTPUT_H0D1 (0x17) -#endif diff --git a/lib/MySensors/hal/architecture/NRF5/drivers/nrf5_wiring_digital.c b/lib/MySensors/hal/architecture/NRF5/drivers/nrf5_wiring_digital.c deleted file mode 100644 index 3ab490fb..00000000 --- a/lib/MySensors/hal/architecture/NRF5/drivers/nrf5_wiring_digital.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright (c) 2015 Arduino LLC. All right reserved. - Copyright (c) 2016 Sandeep Mistry All right reserved. - Copyright (c) 2017 Frank Holtz All right reserved. - - 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 "nrf.h" - -#include "Arduino.h" -#include "nrf5_wiring_constants.h" - -#ifdef __cplusplus -extern "C" { -#endif -void nrf5_pinMode(uint32_t ulPin, uint32_t ulMode) -{ - if (ulPin >= PINS_COUNT) { - return; - } - -#ifdef ARDUINO_ARCH_NRF52 - // Arduino: https://github.com/arduino-org/arduino-core-nrf52 - ulPin = g_APinDescription[ulPin].ulPin; -#else - // Sandeep Mistry: https://github.com/sandeepmistry/arduino-nRF5 - ulPin = g_ADigitalPinMap[ulPin]; -#endif - - // Set pin mode according to chapter '22.6.3 I/O Pin Configuration' - switch (ulMode) { - case INPUT: - // Set pin to input mode - NRF_GPIO->PIN_CNF[ulPin] = - ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | - ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | - ((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | - ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | - ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); - break; - - case INPUT_PULLUP: - // Set pin to input mode with pull-up resistor enabled - NRF_GPIO->PIN_CNF[ulPin] = - ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | - ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | - ((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | - ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | - ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); - break; - - case INPUT_PULLDOWN: - // Set pin to input mode with pull-down resistor enabled - NRF_GPIO->PIN_CNF[ulPin] = - ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | - ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | - ((uint32_t)GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos) | - ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | - ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); - break; - - case OUTPUT: - // Set pin to output mode - NRF_GPIO->PIN_CNF[ulPin] = - ((uint32_t)GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | - ((uint32_t)GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | - ((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | - ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | - ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); - break; - - default: - // calculate nRF specific output modes - if ((ulMode >= OUTPUT_S0S1) && (ulMode <= OUTPUT_H0D1)) { - // Set pin to given output mode - NRF_GPIO->PIN_CNF[ulPin] = - ((uint32_t)GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | - ((uint32_t)GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | - ((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | - ((uint32_t)(ulMode - OUTPUT_S0S1) << GPIO_PIN_CNF_DRIVE_Pos) | - ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); - } - break; - } -} - -#ifdef __cplusplus -} -#endif diff --git a/lib/MySensors/hal/architecture/NRF5/drivers/nrf_temp.h b/lib/MySensors/hal/architecture/NRF5/drivers/nrf_temp.h deleted file mode 100644 index ae5c2ecf..00000000 --- a/lib/MySensors/hal/architecture/NRF5/drivers/nrf_temp.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NRF_TEMP_H__ -#define NRF_TEMP_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define MASK_SIGN (0x00000200UL) //!< MASK_SIGN -#define MASK_SIGN_EXTENSION (0xFFFFFC00UL) //!< MASK_SIGN_EXTENSION - -/** - * @brief Function for preparing the temp module for temperature measurement. - * - * This function initializes the TEMP module and writes to the hidden configuration register. - */ -static __INLINE void nrf_temp_init(void) -{ - /**@note Workaround for PAN_028 rev2.0A anomaly 31 - TEMP: Temperature offset value has to be manually loaded to the TEMP module */ - *(uint32_t *) 0x4000C504 = 0; -} - -/** - * @brief Function for reading temperature measurement. - * - * The function reads the 10 bit 2's complement value and transforms it to a 32 bit 2's complement value. - */ -static __INLINE int32_t nrf_temp_read(void) -{ - /**@note Workaround for PAN_028 rev2.0A anomaly 28 - TEMP: Negative measured values are not represented correctly */ - return ((NRF_TEMP->TEMP & MASK_SIGN) != 0) ? (int32_t)(NRF_TEMP->TEMP | MASK_SIGN_EXTENSION) : - (NRF_TEMP->TEMP); -} - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/MySensors/hal/architecture/NRF5/drivers/wdt.h b/lib/MySensors/hal/architecture/NRF5/drivers/wdt.h deleted file mode 100644 index e6745958..00000000 --- a/lib/MySensors/hal/architecture/NRF5/drivers/wdt.h +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright (c) 2002, 2004 Marek Michalkiewicz - Copyright (c) 2005, 2006, 2007 Eric B. Weddington - Copyright (c) 2016 Frank Holtz - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. */ - -/* $Id$ */ - -/* - avr/wdt.h - macros for AVR watchdog timer - */ - -#ifndef _NRF5_WDT_H_ -#define _NRF5_WDT_H_ - -#include -#include - -/** \file */ -/** \defgroup avr_watchdog : Watchdog timer handling - \code #include \endcode - @ingroup internals - - This header file declares the interface to some inline macros - handling the watchdog timer like present in many AVR devices. - In order to prevent the watchdog timer configuration from being - accidentally altered by a crashing application, a special timed - sequence is required in order to change it. The macros within - this header file handle the required sequence automatically - before changing any value. Interrupts will be disabled during - the manipulation. -*/ - -/** - \ingroup avr_watchdog - Reset the watchdog timer. When the watchdog timer is enabled, - a call to this instruction is required before the timer expires, - otherwise a watchdog-initiated device reset will occur. -*/ - -#define wdt_reset() NRF_WDT->RR[0] = WDT_RR_RR_Reload - -/** - \ingroup avr_watchdog - Enable the watchdog timer, configuring it for expiry after - \c timeout (ms). - - The WDT is running in sleep mode. - - See also the symbolic constants \c WDTO_15MS et al. -*/ -#define wdt_enable(timeout) \ - NRF_WDT->CONFIG = NRF_WDT->CONFIG = (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos) | ( WDT_CONFIG_SLEEP_Run << WDT_CONFIG_SLEEP_Pos); \ - NRF_WDT->CRV = (32768*timeout)/1000; \ - NRF_WDT->RREN |= WDT_RREN_RR0_Msk; \ - NRF_WDT->TASKS_START = 1 - -/** - \ingroup avr_watchdog - Disable the watchdog timer. On nRF5 the timer cannot disabled. - The period is set to 36h of CPU run time. The WDT is stopped in sleep mode. -*/ -#define wdt_disable() \ - NRF_WDT->CONFIG = NRF_WDT->CONFIG = (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos) | ( WDT_CONFIG_SLEEP_Pause << WDT_CONFIG_SLEEP_Pos); \ - NRF_WDT->CRV = 4294967295 - -/** - \ingroup avr_watchdog - Symbolic constants for the watchdog timeout. - - Possible timeout values are: 15 ms, 30 ms, 60 ms, 120 ms, 250 ms, - 500 ms, 1 s, 2 s, 4s, 8s. (Not all devices allow 4 s or 8 s.) - Symbolic constants are formed by the prefix - \c WDTO_, followed by the time. - - Example that would select a watchdog timer expiry of approximately - 500 ms: - \code - wdt_enable(WDTO_500MS); - \endcode -*/ -#define WDTO_15MS 15 - -/** \ingroup avr_watchdog - See \c WDTO_15MS */ -#define WDTO_30MS 30 - -/** \ingroup avr_watchdog - See \c WDTO_15MS */ -#define WDTO_60MS 60 - -/** \ingroup avr_watchdog - See \c WDTO_15MS */ -#define WDTO_120MS 120 - -/** \ingroup avr_watchdog - See \c WDTO_15MS */ -#define WDTO_250MS 250 - -/** \ingroup avr_watchdog - See \c WDTO_15MS */ -#define WDTO_500MS 500 - -/** \ingroup avr_watchdog - See \c WDTO_15MS */ -#define WDTO_1S 1000 - -/** \ingroup avr_watchdog - See \c WDTO_15MS */ -#define WDTO_2S 2000 - -/** \ingroup avr_watchdog - See \c WDTO_15MS - Note: This is only available on the - ATtiny2313, - ATtiny24, ATtiny44, ATtiny84, ATtiny84A, - ATtiny25, ATtiny45, ATtiny85, - ATtiny261, ATtiny461, ATtiny861, - ATmega48, ATmega88, ATmega168, - ATmega48P, ATmega88P, ATmega168P, ATmega328P, - ATmega164P, ATmega324P, ATmega644P, ATmega644, - ATmega640, ATmega1280, ATmega1281, ATmega2560, ATmega2561, - ATmega8HVA, ATmega16HVA, ATmega32HVB, - ATmega406, ATmega1284P, - AT90PWM1, AT90PWM2, AT90PWM2B, AT90PWM3, AT90PWM3B, AT90PWM216, AT90PWM316, - AT90PWM81, AT90PWM161, - AT90USB82, AT90USB162, - AT90USB646, AT90USB647, AT90USB1286, AT90USB1287, - ATtiny48, ATtiny88, - nRF51822, nRF52832 - */ -#define WDTO_4S 4000 - -/** \ingroup avr_watchdog - See \c WDTO_15MS - Note: This is only available on the - ATtiny2313, - ATtiny24, ATtiny44, ATtiny84, ATtiny84A, - ATtiny25, ATtiny45, ATtiny85, - ATtiny261, ATtiny461, ATtiny861, - ATmega48, ATmega48A, ATmega48PA, ATmega88, ATmega168, - ATmega48P, ATmega88P, ATmega168P, ATmega328P, - ATmega164P, ATmega324P, ATmega644P, ATmega644, - ATmega640, ATmega1280, ATmega1281, ATmega2560, ATmega2561, - ATmega8HVA, ATmega16HVA, ATmega32HVB, - ATmega406, ATmega1284P, - ATmega2564RFR2, ATmega256RFR2, ATmega1284RFR2, ATmega128RFR2, ATmega644RFR2, ATmega64RFR2 - AT90PWM1, AT90PWM2, AT90PWM2B, AT90PWM3, AT90PWM3B, AT90PWM216, AT90PWM316, - AT90PWM81, AT90PWM161, - AT90USB82, AT90USB162, - AT90USB646, AT90USB647, AT90USB1286, AT90USB1287, - ATtiny48, ATtiny88, - ATxmega16a4u, ATxmega32a4u, - ATxmega16c4, ATxmega32c4, - ATxmega128c3, ATxmega192c3, ATxmega256c3, - nRF51822, nRF52832 - */ -#define WDTO_8S 8000 - -#endif /* _NRF5_WDT_H_ */ diff --git a/lib/MySensors/hal/architecture/SAMD/MyHwSAMD.cpp b/lib/MySensors/hal/architecture/SAMD/MyHwSAMD.cpp deleted file mode 100644 index c225ddbb..00000000 --- a/lib/MySensors/hal/architecture/SAMD/MyHwSAMD.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHwSAMD.h" - -/* -int8_t pinIntTrigger = 0; -void wakeUp() //place to send the interrupts -{ - pinIntTrigger = 1; -} -void wakeUp2() //place to send the second interrupts -{ - pinIntTrigger = 2; -} - -// Watchdog Timer interrupt service routine. This routine is required -// to allow automatic WDIF and WDIE bit clearance in hardware. -ISR (WDT_vect) -{ - // WDIE & WDIF is cleared in hardware upon entering this ISR - wdt_disable(); -} -*/ - - -void hwReadConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *dst = static_cast(buf); - const int offs = reinterpret_cast(addr); - (void)eep.read(offs, dst, length); -} - -void hwWriteConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *src = static_cast(buf); - const int offs = reinterpret_cast(addr); - // use update() instead of write() to reduce e2p wear off - (void)eep.update(offs, src, length); -} - -uint8_t hwReadConfig(const int addr) -{ - return eep.read(addr); -} - -void hwWriteConfig(const int addr, uint8_t value) -{ - (void)eep.update(addr, value); -} - -bool hwInit(void) -{ -#if !defined(MY_DISABLED_SERIAL) - MY_SERIALDEVICE.begin(MY_BAUD_RATE); -#if defined(MY_GATEWAY_SERIAL) - while (!MY_SERIALDEVICE) {} -#endif -#endif - - SYSCTRL->VREF.reg |= SYSCTRL_VREF_TSEN; // Enable the temperature sensor - while (ADC->STATUS.bit.SYNCBUSY == - 1); // Wait for synchronization of registers between the clock domains - - const uint8_t eepInit = eep.begin(MY_EXT_EEPROM_TWI_CLOCK, &Wire); -#if defined(SENSEBENDER_GW_SAMD_V1) - // check connection to external EEPROM - only sensebender GW - return eepInit==0; -#else - (void)eepInit; - return true; -#endif -} - -void hwWatchdogReset(void) -{ - // TODO: Not supported! -} - -void hwReboot(void) -{ - NVIC_SystemReset(); - while (true); -} - -int8_t hwSleep(uint32_t ms) -{ - // TODO: Not supported! - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt; - (void)mode; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, - uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -bool hwUniqueID(unique_id_t *uniqueID) -{ - (void)memcpy((uint8_t *)uniqueID, (uint32_t *)0x0080A00C, 4); - (void)memcpy((uint8_t *)uniqueID + 4, (uint32_t *)0x0080A040, 12); - return true; -} - -// Wait for synchronization of registers between the clock domains -static __inline__ void syncADC() __attribute__((always_inline, unused)); -static void syncADC() -{ - while (ADC->STATUS.bit.SYNCBUSY); -} - -uint16_t hwCPUVoltage(void) -{ - // Set ADC reference to internal 1v - ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; - ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val; - syncADC(); - // Set to 10 bits reading resolution - ADC->CTRLB.reg = ADC_CTRLB_RESSEL_10BIT | ADC_CTRLB_PRESCALER_DIV256; - syncADC(); - // Select MUXPOS as SCALEDIOVCC/4 channel, and MUXNEG as internal ground - ADC->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_SCALEDIOVCC_Val; - ADC->INPUTCTRL.bit.MUXNEG = ADC_INPUTCTRL_MUXNEG_GND_Val; - syncADC(); - // enable ADC - ADC->CTRLA.bit.ENABLE = 1; - syncADC(); - // start conversion - ADC->SWTRIG.bit.START = 1; - // clear the Data Ready flag - ADC->INTFLAG.bit.RESRDY = 1; - syncADC(); - // start conversion again, since The first conversion after the reference is changed must not be used. - ADC->SWTRIG.bit.START = 1; - // waiting for conversion to complete - while (!ADC->INTFLAG.bit.RESRDY); - syncADC(); - const uint32_t valueRead = ADC->RESULT.reg; - // disable ADC - ADC->CTRLA.bit.ENABLE = 0; - syncADC(); - // value is 1/4 scaled, multiply by 4 - return valueRead * 4; -} - -uint16_t hwCPUFrequency(void) -{ - // TODO: currently reporting compile time frequency (in 1/10MHz) - return F_CPU / 100000UL; -} - -int8_t hwCPUTemperature(void) -{ - // taken from https://github.com/arduino/ArduinoCore-samd/pull/277 - // Set to 12 bits resolution - ADC->CTRLB.reg = ADC_CTRLB_RESSEL_12BIT | ADC_CTRLB_PRESCALER_DIV256; - syncADC(); - // Ensure we are sampling slowly - ADC->SAMPCTRL.reg = ADC_SAMPCTRL_SAMPLEN(0x3f); - syncADC(); - // Set ADC reference to internal 1v - ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; - ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val; - syncADC(); - // Select MUXPOS as temperature channel, and MUXNEG as internal ground - ADC->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_TEMP_Val; - ADC->INPUTCTRL.bit.MUXNEG = ADC_INPUTCTRL_MUXNEG_GND_Val; - syncADC(); - // Enable ADC - ADC->CTRLA.bit.ENABLE = 1; - syncADC(); - // Start ADC conversion - ADC->SWTRIG.bit.START = 1; - // Clear the Data Ready flag - ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY; - syncADC(); - // Start conversion again, since The first conversion after the reference is changed must not be used. - ADC->SWTRIG.bit.START = 1; - // Wait until ADC conversion is done - while (!(ADC->INTFLAG.bit.RESRDY)); - syncADC(); - // Get result - // This is signed so that the math later is done signed - const int32_t adcReading = ADC->RESULT.reg; - // Clear result ready flag - ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY; - syncADC(); - // Disable ADC - ADC->CTRLA.bit.ENABLE = 0; - syncADC(); - // Factory room temperature readings - const uint8_t roomInteger = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_INT_ADDR & - FUSES_ROOM_TEMP_VAL_INT_Msk) - >> FUSES_ROOM_TEMP_VAL_INT_Pos; - const uint8_t roomDecimal = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_DEC_ADDR & - FUSES_ROOM_TEMP_VAL_DEC_Msk) - >> FUSES_ROOM_TEMP_VAL_DEC_Pos; - const int32_t roomReading = ((*(uint32_t *)FUSES_ROOM_ADC_VAL_ADDR & FUSES_ROOM_ADC_VAL_Msk) >> - FUSES_ROOM_ADC_VAL_Pos); - const int32_t roomTemperature = 1000 * roomInteger + 100 * roomDecimal; - // Factory hot temperature readings - const uint8_t hotInteger = (*(uint32_t *)FUSES_HOT_TEMP_VAL_INT_ADDR & FUSES_HOT_TEMP_VAL_INT_Msk) - >> - FUSES_HOT_TEMP_VAL_INT_Pos; - const uint8_t hotDecimal = (*(uint32_t *)FUSES_HOT_TEMP_VAL_DEC_ADDR & FUSES_HOT_TEMP_VAL_DEC_Msk) - >> - FUSES_HOT_TEMP_VAL_DEC_Pos; - const int32_t hotReading = ((*(uint32_t *)FUSES_HOT_ADC_VAL_ADDR & FUSES_HOT_ADC_VAL_Msk) >> - FUSES_HOT_ADC_VAL_Pos); - const int32_t hotTemperature = 1000 * hotInteger + 100 * hotDecimal; - // Linear interpolation of temperature using factory room temperature and hot temperature - const int32_t temperature = roomTemperature + ((hotTemperature - roomTemperature) * - (adcReading - roomReading)) / (hotReading - roomReading); - return static_cast(((temperature / 1000) - MY_SAMD_TEMPERATURE_OFFSET) / - MY_SAMD_TEMPERATURE_GAIN); -} - - -uint16_t hwFreeMem(void) -{ - // TODO: Not supported! - return FUNCTION_NOT_SUPPORTED; -} diff --git a/lib/MySensors/hal/architecture/SAMD/MyHwSAMD.h b/lib/MySensors/hal/architecture/SAMD/MyHwSAMD.h deleted file mode 100644 index 3b294001..00000000 --- a/lib/MySensors/hal/architecture/SAMD/MyHwSAMD.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ -#ifndef MyHwSAMD_h -#define MyHwSAMD_h - -#include -#include - -#ifdef __cplusplus -#include -#endif - -#define CRYPTO_LITTLE_ENDIAN - -#ifndef MY_SERIALDEVICE -#define MY_SERIALDEVICE SerialUSB -#endif - -#ifndef MY_DEBUGDEVICE -#define MY_DEBUGDEVICE MY_SERIALDEVICE -#endif - -#ifndef MY_SAMD_TEMPERATURE_OFFSET -#define MY_SAMD_TEMPERATURE_OFFSET (0.0f) -#endif - -#ifndef MY_SAMD_TEMPERATURE_GAIN -#define MY_SAMD_TEMPERATURE_GAIN (1.0f) -#endif - -// defines for sensebender gw variant.h -#define MY_EXT_EEPROM_I2C_ADDRESS (0x50u) -#define MY_EXT_EEPROM_SIZE (kbits_512) -#define MY_EXT_EEPROM_PAGE_SIZE (32u) - -extEEPROM eep(MY_EXT_EEPROM_SIZE, 1, MY_EXT_EEPROM_PAGE_SIZE, - MY_EXT_EEPROM_I2C_ADDRESS); //device size, number of devices, page size - -#define MY_EXT_EEPROM_TWI_CLOCK (eep.twiClock100kHz) // can be set to 400kHz with precaution if other i2c devices on bus - -#define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__) -#define vsnprintf_P(s, n, f, ...) vsnprintf((s), (n), (f), __VA_ARGS__) - -// redefine 8 bit types of inttypes.h (as of SAMD board defs 1.8.1) -#undef PRId8 -#undef PRIi8 -#undef PRIo8 -#undef PRIu8 -#undef PRIx8 -#undef PRIX8 -#undef PRIdLEAST8 -#undef PRIiLEAST8 -#undef PRIoLEAST8 -#undef PRIuLEAST8 -#undef PRIxLEAST8 -#undef PRIXLEAST8 -#undef PRIdFAST8 -#undef PRIiFAST8 -#undef PRIoFAST8 -#undef PRIuFAST8 -#undef PRIxFAST8 -#undef PRIXFAST8 -#define PRId8 "d" -#define PRIi8 "i" -#define PRIo8 "o" -#define PRIu8 "u" -#define PRIx8 "x" -#define PRIX8 "X" -#define PRIdLEAST8 "d" -#define PRIiLEAST8 "i" -#define PRIoLEAST8 "o" -#define PRIuLEAST8 "u" -#define PRIxLEAST8 "x" -#define PRIXLEAST8 "X" -#define PRIdFAST8 "d" -#define PRIiFAST8 "i" -#define PRIoFAST8 "o" -#define PRIuFAST8 "u" -#define PRIxFAST8 "x" -#define PRIXFAST8 "X" - -// Define these as macros to save valuable space -#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value) -#define hwDigitalRead(__pin) digitalRead(__pin) -#define hwPinMode(__pin, __value) pinMode(__pin, __value) -#define hwMillis() millis() -#define hwRandomNumberInit() randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)) -#define hwGetSleepRemaining() (0ul) - -bool hwInit(void); -void hwWatchdogReset(void); -void hwReboot(void); -void hwReadConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfig(const int addr, uint8_t value); -uint8_t hwReadConfig(const int addr); - -// SOFTSPI -#ifdef MY_SOFTSPI -#error Soft SPI is not available on this architecture! -#endif -#define hwSPI SPI //!< hwSPI - - -/** - * Disable all interrupts. - * Helper function for MY_CRITICAL_SECTION. - */ -static __inline__ uint8_t __disableIntsRetVal(void) -{ - __disable_irq(); - return 1; -} - -/** - * Restore priority mask register. - * Helper function for MY_CRITICAL_SECTION. - */ -static __inline__ void __priMaskRestore(const uint32_t *priMask) -{ - __set_PRIMASK(*priMask); -} - -#ifndef DOXYGEN -#define MY_CRITICAL_SECTION for ( uint32_t __savePriMask __attribute__((__cleanup__(__priMaskRestore))) = __get_PRIMASK(), __ToDo = __disableIntsRetVal(); __ToDo ; __ToDo = 0 ) -#endif /* DOXYGEN */ - -#endif // #ifdef ARDUINO_ARCH_SAMD diff --git a/lib/MySensors/hal/architecture/SAMD/MyMainSAMD.cpp b/lib/MySensors/hal/architecture/SAMD/MyMainSAMD.cpp deleted file mode 100644 index cf734e62..00000000 --- a/lib/MySensors/hal/architecture/SAMD/MyMainSAMD.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -// Initialize library and handle sketch functions like we want to - -extern "C" void __libc_init_array(void); - -int main(void) -{ - init(); -#if defined(USBCON) - __libc_init_array(); - USBDevice.init(); - USBDevice.attach(); -#endif - _begin(); // Startup MySensors library - for(;;) { - _process(); // Process incoming data - if (loop) { - loop(); // Call sketch loop - } - if (serialEventRun) { - serialEventRun(); - } - } - return 0; -} diff --git a/lib/MySensors/hal/architecture/STM32F1/MyHwSTM32F1.cpp b/lib/MySensors/hal/architecture/STM32F1/MyHwSTM32F1.cpp deleted file mode 100644 index 3065ee73..00000000 --- a/lib/MySensors/hal/architecture/STM32F1/MyHwSTM32F1.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHwSTM32F1.h" - -/* -* Pinout STM32F103C8 dev board: -* http://wiki.stm32duino.com/images/a/ae/Bluepillpinout.gif -* -* Wiring RFM69 radio / SPI1 -* -------------------------------------------------- -* CLK PA5 -* MISO PA6 -* MOSI PA7 -* CSN PA4 -* CE NA -* IRQ PA3 (default) -* -* Wiring RF24 radio / SPI1 -* -------------------------------------------------- -* CLK PA5 -* MISO PA6 -* MOSI PA7 -* CSN PA4 -* CE PB0 (default) -* IRQ NA -* -*/ -bool hwInit(void) -{ -#if !defined(MY_DISABLED_SERIAL) - MY_SERIALDEVICE.begin(MY_BAUD_RATE); -#if defined(MY_GATEWAY_SERIAL) - while (!MY_SERIALDEVICE) {} -#endif -#endif - if (EEPROM.init() == EEPROM_OK) { - uint16 cnt; - EEPROM.count(&cnt); - if(cnt>=EEPROM.maxcount()) { - // tmp, WIP: format eeprom if full - EEPROM.format(); - } - return true; - } - return false; -} - -void hwReadConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *dst = static_cast(buf); - int pos = reinterpret_cast(addr); - while (length-- > 0) { - *dst++ = EEPROM.read(pos++); - } -} - -void hwWriteConfigBlock(void *buf, void *addr, size_t length) -{ - uint8_t *src = static_cast(buf); - int pos = reinterpret_cast(addr); - while (length-- > 0) { - EEPROM.write(pos++, *src++); - } -} - -uint8_t hwReadConfig(const int addr) -{ - uint8_t value; - hwReadConfigBlock(&value, reinterpret_cast(addr), 1); - return value; -} - -void hwWriteConfig(const int addr, uint8_t value) -{ - hwWriteConfigBlock(&value, reinterpret_cast(addr), 1); -} - -int8_t hwSleep(uint32_t ms) -{ - // TODO: Not supported! - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt; - (void)mode; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, - uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - - -void hwRandomNumberInit(void) -{ - // use internal temperature sensor as noise source - adc_reg_map *regs = ADC1->regs; - regs->CR2 |= ADC_CR2_TSVREFE; - regs->SMPR1 |= ADC_SMPR1_SMP16; - - uint32_t seed = 0; - uint16_t currentValue = 0; - uint16_t newValue = 0; - - for (uint8_t i = 0; i < 32; i++) { - const uint32_t timeout = hwMillis() + 20; - while (timeout >= hwMillis()) { - newValue = adc_read(ADC1, 16); - if (newValue != currentValue) { - currentValue = newValue; - break; - } - } - seed ^= ( (newValue + hwMillis()) & 7) << i; - } - randomSeed(seed); - regs->CR2 &= ~ADC_CR2_TSVREFE; // disable VREFINT and temp sensor -} - -bool hwUniqueID(unique_id_t *uniqueID) -{ - (void)memcpy((uint8_t *)uniqueID, (uint32_t *)0x1FFFF7E0, 16); // FlashID + ChipID - return true; -} - -uint16_t hwCPUVoltage(void) -{ - adc_reg_map *regs = ADC1->regs; - regs->CR2 |= ADC_CR2_TSVREFE; // enable VREFINT and temp sensor - regs->SMPR1 = ADC_SMPR1_SMP17; // sample rate for VREFINT ADC channel - adc_calibrate(ADC1); - - const uint16_t vdd = adc_read(ADC1, 17); - regs->CR2 &= ~ADC_CR2_TSVREFE; // disable VREFINT and temp sensor - return (uint16_t)(1200u * 4096u / vdd); -} - -uint16_t hwCPUFrequency(void) -{ - return F_CPU/100000UL; -} - -int8_t hwCPUTemperature(void) -{ - adc_reg_map *regs = ADC1->regs; - regs->CR2 |= ADC_CR2_TSVREFE; // enable VREFINT and Temperature sensor - regs->SMPR1 |= ADC_SMPR1_SMP16 | ADC_SMPR1_SMP17; - adc_calibrate(ADC1); - - //const uint16_t adc_temp = adc_read(ADC1, 16); - //const uint16_t vref = 1200 * 4096 / adc_read(ADC1, 17); - // calibrated at 25°C, ADC output = 1430mV, avg slope = 4.3mV / °C, increasing temp ~ lower voltage - const int8_t temp = static_cast((1430.0 - (adc_read(ADC1, 16) * 1200 / adc_read(ADC1, - 17))) / 4.3 + 25.0); - regs->CR2 &= ~ADC_CR2_TSVREFE; // disable VREFINT and temp sensor - return (temp - MY_STM32F1_TEMPERATURE_OFFSET) / MY_STM32F1_TEMPERATURE_GAIN; -} - -uint16_t hwFreeMem(void) -{ - //Not yet implemented - return FUNCTION_NOT_SUPPORTED; -} diff --git a/lib/MySensors/hal/architecture/STM32F1/MyHwSTM32F1.h b/lib/MySensors/hal/architecture/STM32F1/MyHwSTM32F1.h deleted file mode 100644 index b6e8617c..00000000 --- a/lib/MySensors/hal/architecture/STM32F1/MyHwSTM32F1.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyHwSTM32F1_h -#define MyHwSTM32F1_h - -#include -#include -#include -#include - -#ifdef __cplusplus -#include -#endif - -#define CRYPTO_LITTLE_ENDIAN - -#ifndef MY_SERIALDEVICE -#define MY_SERIALDEVICE Serial -#endif - -#ifndef MY_DEBUGDEVICE -#define MY_DEBUGDEVICE MY_SERIALDEVICE -#endif - -#ifndef MY_STM32F1_TEMPERATURE_OFFSET -#define MY_STM32F1_TEMPERATURE_OFFSET (0.0f) -#endif - -#ifndef MY_STM32F1_TEMPERATURE_GAIN -#define MY_STM32F1_TEMPERATURE_GAIN (1.0f) -#endif - -// SS default -#ifndef SS -#define SS PA4 -#endif - -// mapping -#define snprintf_P snprintf -#define vsnprintf_P vsnprintf -#define strncpy_P strncpy -#define printf_P printf -#define yield() // not defined - -#ifndef digitalPinToInterrupt -#define digitalPinToInterrupt(__pin) (__pin) -#endif - -#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value) -#define hwDigitalRead(__pin) digitalRead(__pin) -#define hwPinMode(__pin, __value) pinMode(__pin, __value) -#define hwWatchdogReset() iwdg_feed() -#define hwReboot() nvic_sys_reset() -#define hwMillis() millis() -#define hwGetSleepRemaining() (0ul) - -extern void serialEventRun(void) __attribute__((weak)); -bool hwInit(void); -void hwRandomNumberInit(void); -void hwReadConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfigBlock(void *buf, void *addr, size_t length); -void hwWriteConfig(const int addr, uint8_t value); -uint8_t hwReadConfig(const int addr); - -// SOFTSPI -#ifdef MY_SOFTSPI -#error Soft SPI is not available on this architecture! -#endif -#define hwSPI SPI //!< hwSPI - - -#ifndef DOXYGEN -#define MY_CRITICAL_SECTION -#endif /* DOXYGEN */ - -#endif diff --git a/lib/MySensors/hal/architecture/STM32F1/MyMainSTM32F1.cpp b/lib/MySensors/hal/architecture/STM32F1/MyMainSTM32F1.cpp deleted file mode 100644 index 8531997f..00000000 --- a/lib/MySensors/hal/architecture/STM32F1/MyMainSTM32F1.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -// Force init to be called *first*, i.e. before static object allocation. -// Otherwise, statically allocated objects that need libmaple may fail. -__attribute__(( constructor (101))) void premain() -{ - init(); -} - -// Initialize library and handle sketch functions like we want to -int main(void) -{ - _begin(); // Startup MySensors library - for(;;) { - _process(); // Process incoming data - if (loop) { // Call sketch loop - loop(); - } - if (serialEventRun) { - serialEventRun(); - } - } - return 0; -} \ No newline at end of file diff --git a/lib/MySensors/hal/architecture/Teensy3/MyHwTeensy3.cpp b/lib/MySensors/hal/architecture/Teensy3/MyHwTeensy3.cpp deleted file mode 100644 index bb12daca..00000000 --- a/lib/MySensors/hal/architecture/Teensy3/MyHwTeensy3.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/** -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - -#include "MyHwTeensy3.h" - - -/* -int8_t pinIntTrigger = 0; -void wakeUp() //place to send the interrupts -{ - pinIntTrigger = 1; -} -void wakeUp2() //place to send the second interrupts -{ - pinIntTrigger = 2; -} - -// Watchdog Timer interrupt service routine. This routine is required -// to allow automatic WDIF and WDIE bit clearance in hardware. -ISR (WDT_vect) -{ - // WDIE & WDIF is cleared in hardware upon entering this ISR - wdt_disable(); -} -*/ - -bool hwInit(void) -{ -#if !defined(MY_DISABLED_SERIAL) - MY_SERIALDEVICE.begin(MY_BAUD_RATE); -#if defined(MY_GATEWAY_SERIAL) - while (!MY_SERIALDEVICE) {} -#endif -#endif - return true; -} - -void hwWatchdogReset(void) -{ - // TODO: Not supported! -} - -void hwReboot(void) -{ - SCB_AIRCR = 0x05FA0004; - while (true); -} - -int8_t hwSleep(uint32_t ms) -{ - // TODO: Not supported! - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt; - (void)mode; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, - const uint8_t mode2, - uint32_t ms) -{ - // TODO: Not supported! - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; -} - -bool hwUniqueID(unique_id_t *uniqueID) -{ -#if defined(__MKL26Z64__) - (void)memcpy((uint8_t *)uniqueID, &SIM_UIDMH, 12); - (void)memset((uint8_t *)uniqueID + 12, MY_HWID_PADDING_BYTE, 4); -#else - (void)memcpy((uint8_t *)uniqueID, &SIM_UIDH, 16); -#endif - return true; -} - -uint16_t hwCPUVoltage(void) -{ - analogReference(DEFAULT); - analogReadResolution(12); - analogReadAveraging(32); -#if defined(__MK20DX128__) || defined(__MK20DX256__) - // Teensy 3.0/3.1/3.2 - return (uint16_t)(1195u * 4096u / analogRead(39)); -#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) - // Teensy 3.6 - return (uint16_t)(1195u * 4096u / analogRead(71)); -#elif defined(__MKL26Z64__) - // Teensy LC - // not supported - return FUNCTION_NOT_SUPPORTED; -#else - // not supported - return FUNCTION_NOT_SUPPORTED; -#endif -} - -uint16_t hwCPUFrequency(void) -{ - // TODO: currently reporting compile time frequency (in 1/10MHz) - return F_CPU / 100000UL; -} - -int8_t hwCPUTemperature(void) -{ - return -127; // not implemented yet -} - -uint16_t hwFreeMem(void) -{ - // TODO: Not supported! - return FUNCTION_NOT_SUPPORTED; -} - -#if defined(MY_HW_HAS_GETENTROPY) -ssize_t hwGetentropy(void *__buffer, const size_t __length) -{ - SIM_SCGC6 |= SIM_SCGC6_RNGA; // enable RNG - RNG_CR &= ~RNG_CR_SLP_MASK; - RNG_CR |= RNG_CR_HA_MASK; //high assurance, not needed - size_t pos = 0; - while (pos < __length) { - RNG_CR |= RNG_CR_GO_MASK; - while (!(RNG_SR & RNG_SR_OREG_LVL(0xF))); - const uint32_t rndVar = RNG_OR; - const uint8_t bsize = (__length - pos) > sizeof(rndVar) ? sizeof(rndVar) : (__length - pos); - (void)memcpy((uint8_t *)__buffer + pos, &rndVar, bsize); - pos += bsize; - } - SIM_SCGC6 &= ~SIM_SCGC6_RNGA; // disable RNG - return pos; -} -#endif - -void hwRandomNumberInit(void) -{ -#if defined(MY_HW_HAS_GETENTROPY) - // use HW RNG present on Teensy3.5/3.6 - // init RNG - uint32_t seed = 0; - hwGetentropy(&seed, sizeof(seed)); - randomSeed(seed); -#else - randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)); -#endif -} diff --git a/lib/MySensors/hal/architecture/Teensy3/MyHwTeensy3.h b/lib/MySensors/hal/architecture/Teensy3/MyHwTeensy3.h deleted file mode 100644 index 9d344647..00000000 --- a/lib/MySensors/hal/architecture/Teensy3/MyHwTeensy3.h +++ /dev/null @@ -1,91 +0,0 @@ -/** -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* Radio wiring Teensy3.x: RF24, RFM69, RFM95: -* MISO 12 -* MOSI 11 -* SCK 13 -* CSN 10 -* CE 9 (RF24) -* IRQ 8 (opt. RF24, RFM69, RFM95) -*/ - -#ifndef MyHwTeensy3_h -#define MyHwTeensy3_h - -#include -#include "util/atomic.h" - -#ifdef __cplusplus -#include -#endif - -#define CRYPTO_LITTLE_ENDIAN - -#ifndef MY_SERIALDEVICE -#define MY_SERIALDEVICE Serial -#endif - -#ifndef MY_DEBUGDEVICE -#define MY_DEBUGDEVICE MY_SERIALDEVICE -#endif - -#if defined(__MK64FX512__) || defined(__MK66FX1M0__) -#define RNG_CR_GO_MASK 0x1u -#define RNG_CR_HA_MASK 0x2u -#define RNG_CR_INTM_MASK 0x4u -#define RNG_CR_CLRI_MASK 0x8u -#define RNG_CR_SLP_MASK 0x10u -#define RNG_SR_OREG_LVL_MASK 0xFF00u -#define RNG_SR_OREG_LVL_SHIFT 8 -#define RNG_SR_OREG_LVL(x) (((uint32_t)(((uint32_t)(x))< - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -int main(void) -{ - _begin(); // Startup MySensors library - for(;;) { - _process(); // Process incoming data - if (loop) { - loop(); // Call sketch loop - } - yield(); - } - return 0; -} diff --git a/lib/MySensors/hal/crypto/AVR/MyCryptoAVR.cpp b/lib/MySensors/hal/crypto/AVR/MyCryptoAVR.cpp deleted file mode 100644 index 26176fcd..00000000 --- a/lib/MySensors/hal/crypto/AVR/MyCryptoAVR.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -*/ - -#include "MyCryptoAVR.h" - -// SHA256 implementation in ASM, see MyASM.S -void SHA256(uint8_t *dest, const uint8_t *data, size_t dataLength) -{ - sha256((sha256_hash_t *)dest, data, dataLength << 3); // data length in bits -} - -// SHA256HMAC -void SHA256HMAC(uint8_t *dest, const uint8_t *key, size_t keyLength, const uint8_t *data, - size_t dataLength) -{ - hmac_sha256(dest, key, keyLength << 3, data, dataLength << 3); -} - - -// AES -AES_ctx aes_ctx; - -void AES128CBCInit(const uint8_t *key) -{ - AES_init_ctx(&aes_ctx, key); -} - -void AES128CBCEncrypt(uint8_t *iv, uint8_t *buffer, const size_t dataLength) -{ - AES_ctx_set_iv(&aes_ctx, iv); - AES_CBC_encrypt_buffer(&aes_ctx, buffer, dataLength); -} - -void AES128CBCDecrypt(uint8_t *iv, uint8_t *buffer, const size_t dataLength) -{ - AES_ctx_set_iv(&aes_ctx, iv); - AES_CBC_decrypt_buffer(&aes_ctx, buffer, dataLength); -} - - diff --git a/lib/MySensors/hal/crypto/AVR/MyCryptoAVR.h b/lib/MySensors/hal/crypto/AVR/MyCryptoAVR.h deleted file mode 100644 index 6ab384e0..00000000 --- a/lib/MySensors/hal/crypto/AVR/MyCryptoAVR.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -*/ - -#ifndef MyCryptoGeneric_h -#define MyCryptoGeneric_h - -#include "hal/crypto/MyCryptoHAL.h" -#include "hal/crypto/AVR/drivers/AES/aes.cpp" -#include "hal/crypto/AVR/drivers/SHA256/sha256.cpp" -#include "hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.cpp" - -#endif diff --git a/lib/MySensors/hal/crypto/AVR/drivers/AES/aes.cpp b/lib/MySensors/hal/crypto/AVR/drivers/AES/aes.cpp deleted file mode 100644 index 60b30596..00000000 --- a/lib/MySensors/hal/crypto/AVR/drivers/AES/aes.cpp +++ /dev/null @@ -1,577 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* AES implementation: https://github.com/kokke/tiny-AES-c -*/ - -/* - -This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode. -Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. - -The implementation is verified against the test vectors in: - National Institute of Standards and Technology Special Publication 800-38A 2001 ED - -ECB-AES128 ----------- - - plain-text: - 6bc1bee22e409f96e93d7e117393172a - ae2d8a571e03ac9c9eb76fac45af8e51 - 30c81c46a35ce411e5fbc1191a0a52ef - f69f2445df4f9b17ad2b417be66c3710 - - key: - 2b7e151628aed2a6abf7158809cf4f3c - - resulting cipher - 3ad77bb40d7a3660a89ecaf32466ef97 - f5d3d58503b9699de785895a96fdbaaf - 43b1cd7f598ece23881b00e3ed030688 - 7b0c785e27e8ad3f8223207104725dd4 - - -NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) - You should pad the end of the string with zeros if this is not the case. - For AES192/256 the key size is proportionally larger. - -*/ - - -/*****************************************************************************/ -/* Includes: */ -/*****************************************************************************/ - -#include "aes.h" - -/*****************************************************************************/ -/* Defines: */ -/*****************************************************************************/ -// The number of columns comprising a state in AES. This is a constant in AES. Value=4 -#define Nb 4 - -#if defined(AES256) && (AES256 == 1) -#define Nk 8 -#define Nr 14 -#elif defined(AES192) && (AES192 == 1) -#define Nk 6 -#define Nr 12 -#else -#define Nk 4 // The number of 32 bit words in a key. -#define Nr 10 // The number of rounds in AES Cipher. -#endif - -// jcallan@github points out that declaring Multiply as a function -// reduces code size considerably with the Keil ARM compiler. -// See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3 -#ifndef MULTIPLY_AS_A_FUNCTION -#define MULTIPLY_AS_A_FUNCTION 0 -#endif - -/*****************************************************************************/ -/* Private variables: */ -/*****************************************************************************/ -// state - array holding the intermediate results during decryption. -typedef uint8_t state_t[4][4]; - -// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM -// The numbers below can be computed dynamically trading ROM for RAM - -// This can be useful in (embedded) bootloader applications, where ROM is often limited. -static const uint8_t sbox[256] PROGMEM = { - //0 1 2 3 4 5 6 7 8 9 A B C D E F - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -static const uint8_t rsbox[256] PROGMEM = { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d -}; - -// The round constant word array, Rcon[i], contains the values given by -// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) -static const uint8_t Rcon[11] PROGMEM = { - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 -}; - -/* - * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12), - * that you can remove most of the elements in the Rcon array, because they are unused. - * - * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon - * - * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), - * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." - */ - - -/*****************************************************************************/ -/* Private functions: */ -/*****************************************************************************/ -/* -static uint8_t getSBoxValue(uint8_t num) -{ - return sbox[num]; -} -*/ -#define getSBoxValue(num) pgm_read_byte(&sbox[(num)]) -/* -static uint8_t getSBoxInvert(uint8_t num) -{ - return rsbox[num]; -} -*/ -#define getSBoxInvert(num) pgm_read_byte(&rsbox[(num)]) - -// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. -static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) -{ - unsigned i; - uint8_t tempa[4]; // Used for the column/row operations - - // The first round key is the key itself. - for (i = 0; i < Nk; ++i) { - RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; - RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; - RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; - RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; - } - - // All other round keys are found from the previous round keys. - for (i = Nk; i < Nb * (Nr + 1); ++i) { - unsigned j, k; - { - k = (i - 1) * 4; - tempa[0] = RoundKey[k + 0]; - tempa[1] = RoundKey[k + 1]; - tempa[2] = RoundKey[k + 2]; - tempa[3] = RoundKey[k + 3]; - } - - if (i % Nk == 0) { - // This function shifts the 4 bytes in a word to the left once. - // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] - - // Function RotWord() - { - const uint8_t u8tmp = tempa[0]; - tempa[0] = tempa[1]; - tempa[1] = tempa[2]; - tempa[2] = tempa[3]; - tempa[3] = u8tmp; - } - - // SubWord() is a function that takes a four-byte input word and - // applies the S-box to each of the four bytes to produce an output word. - - // Function Subword() - { - tempa[0] = getSBoxValue(tempa[0]); - tempa[1] = getSBoxValue(tempa[1]); - tempa[2] = getSBoxValue(tempa[2]); - tempa[3] = getSBoxValue(tempa[3]); - } - - tempa[0] = tempa[0] ^ pgm_read_byte(&Rcon[i / Nk]); - } -#if defined(AES256) && (AES256 == 1) - if (i % Nk == 4) { - // Function Subword() - { - tempa[0] = getSBoxValue(tempa[0]); - tempa[1] = getSBoxValue(tempa[1]); - tempa[2] = getSBoxValue(tempa[2]); - tempa[3] = getSBoxValue(tempa[3]); - } - } -#endif - j = i * 4; - k = (i - Nk) * 4; - RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; - RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; - RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; - RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; - } -} - -void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) -{ - KeyExpansion(ctx->RoundKey, key); -} -#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) -void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) -{ - KeyExpansion(ctx->RoundKey, key); - memcpy(ctx->Iv, iv, AES_BLOCKLEN); -} -void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) -{ - memcpy(ctx->Iv, iv, AES_BLOCKLEN); -} -#endif - -// This function adds the round key to state. -// The round key is added to the state by an XOR function. -static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) -{ - uint8_t i, j; - for (i = 0; i < 4; ++i) { - for (j = 0; j < 4; ++j) { - (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; - } - } -} - -// The SubBytes Function Substitutes the values in the -// state matrix with values in an S-box. -static void SubBytes(state_t* state) -{ - uint8_t i, j; - for (i = 0; i < 4; ++i) { - for (j = 0; j < 4; ++j) { - (*state)[j][i] = getSBoxValue((*state)[j][i]); - } - } -} - -// The ShiftRows() function shifts the rows in the state to the left. -// Each row is shifted with different offset. -// Offset = Row number. So the first row is not shifted. -static void ShiftRows(state_t* state) -{ - uint8_t temp; - - // Rotate first row 1 columns to left - temp = (*state)[0][1]; - (*state)[0][1] = (*state)[1][1]; - (*state)[1][1] = (*state)[2][1]; - (*state)[2][1] = (*state)[3][1]; - (*state)[3][1] = temp; - - // Rotate second row 2 columns to left - temp = (*state)[0][2]; - (*state)[0][2] = (*state)[2][2]; - (*state)[2][2] = temp; - - temp = (*state)[1][2]; - (*state)[1][2] = (*state)[3][2]; - (*state)[3][2] = temp; - - // Rotate third row 3 columns to left - temp = (*state)[0][3]; - (*state)[0][3] = (*state)[3][3]; - (*state)[3][3] = (*state)[2][3]; - (*state)[2][3] = (*state)[1][3]; - (*state)[1][3] = temp; -} - -static uint8_t xtime(uint8_t x) -{ - return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); -} - -// MixColumns function mixes the columns of the state matrix -static void MixColumns(state_t* state) -{ - uint8_t i; - for (i = 0; i < 4; ++i) { - uint8_t Tmp, Tm, t; - t = (*state)[i][0]; - Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3]; - Tm = (*state)[i][0] ^ (*state)[i][1]; - Tm = xtime(Tm); - (*state)[i][0] ^= Tm ^ Tmp; - Tm = (*state)[i][1] ^ (*state)[i][2]; - Tm = xtime(Tm); - (*state)[i][1] ^= Tm ^ Tmp; - Tm = (*state)[i][2] ^ (*state)[i][3]; - Tm = xtime(Tm); - (*state)[i][2] ^= Tm ^ Tmp; - Tm = (*state)[i][3] ^ t; - Tm = xtime(Tm); - (*state)[i][3] ^= Tm ^ Tmp; - } -} - -// Multiply is used to multiply numbers in the field GF(2^8) -// Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary -// The compiler seems to be able to vectorize the operation better this way. -// See https://github.com/kokke/tiny-AES-c/pull/34 -#if MULTIPLY_AS_A_FUNCTION -static uint8_t Multiply(uint8_t x, uint8_t y) -{ - return (((y & 1) * x) ^ - ((y >> 1 & 1) * xtime(x)) ^ - ((y >> 2 & 1) * xtime(xtime(x))) ^ - ((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^ - ((y >> 4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */ -} -#else -#define Multiply(x, y) \ - ( ((y & 1) * x) ^ \ - ((y>>1 & 1) * xtime(x)) ^ \ - ((y>>2 & 1) * xtime(xtime(x))) ^ \ - ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ - ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ - -#endif - -#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) -// MixColumns function mixes the columns of the state matrix. -// The method used to multiply may be difficult to understand for the inexperienced. -// Please use the references to gain more information. -static void InvMixColumns(state_t* state) -{ - int i; - for (i = 0; i < 4; ++i) { - uint8_t a, b, c, d; - a = (*state)[i][0]; - b = (*state)[i][1]; - c = (*state)[i][2]; - d = (*state)[i][3]; - - (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); - (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); - (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); - (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); - } -} - - -// The SubBytes Function Substitutes the values in the -// state matrix with values in an S-box. -static void InvSubBytes(state_t* state) -{ - uint8_t i, j; - for (i = 0; i < 4; ++i) { - for (j = 0; j < 4; ++j) { - (*state)[j][i] = getSBoxInvert((*state)[j][i]); - } - } -} - -static void InvShiftRows(state_t* state) -{ - uint8_t temp; - - // Rotate first row 1 columns to right - temp = (*state)[3][1]; - (*state)[3][1] = (*state)[2][1]; - (*state)[2][1] = (*state)[1][1]; - (*state)[1][1] = (*state)[0][1]; - (*state)[0][1] = temp; - - // Rotate second row 2 columns to right - temp = (*state)[0][2]; - (*state)[0][2] = (*state)[2][2]; - (*state)[2][2] = temp; - - temp = (*state)[1][2]; - (*state)[1][2] = (*state)[3][2]; - (*state)[3][2] = temp; - - // Rotate third row 3 columns to right - temp = (*state)[0][3]; - (*state)[0][3] = (*state)[1][3]; - (*state)[1][3] = (*state)[2][3]; - (*state)[2][3] = (*state)[3][3]; - (*state)[3][3] = temp; -} -#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) - -// Cipher is the main function that encrypts the PlainText. -static void Cipher(state_t* state, const uint8_t* RoundKey) -{ - uint8_t round = 0; - - // Add the First round key to the state before starting the rounds. - AddRoundKey(0, state, RoundKey); - - // There will be Nr rounds. - // The first Nr-1 rounds are identical. - // These Nr-1 rounds are executed in the loop below. - for (round = 1; round < Nr; ++round) { - SubBytes(state); - ShiftRows(state); - MixColumns(state); - AddRoundKey(round, state, RoundKey); - } - - // The last round is given below. - // The MixColumns function is not here in the last round. - SubBytes(state); - ShiftRows(state); - AddRoundKey(Nr, state, RoundKey); -} - -#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) -static void InvCipher(state_t* state, const uint8_t* RoundKey) -{ - uint8_t round = 0; - - // Add the First round key to the state before starting the rounds. - AddRoundKey(Nr, state, RoundKey); - - // There will be Nr rounds. - // The first Nr-1 rounds are identical. - // These Nr-1 rounds are executed in the loop below. - for (round = (Nr - 1); round > 0; --round) { - InvShiftRows(state); - InvSubBytes(state); - AddRoundKey(round, state, RoundKey); - InvMixColumns(state); - } - - // The last round is given below. - // The MixColumns function is not here in the last round. - InvShiftRows(state); - InvSubBytes(state); - AddRoundKey(0, state, RoundKey); -} -#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) - -/*****************************************************************************/ -/* Public functions: */ -/*****************************************************************************/ -#if defined(ECB) && (ECB == 1) - - -void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) -{ - // The next function call encrypts the PlainText with the Key using AES algorithm. - Cipher((state_t*)buf, ctx->RoundKey); -} - -void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) -{ - // The next function call decrypts the PlainText with the Key using AES algorithm. - InvCipher((state_t*)buf, ctx->RoundKey); -} - - -#endif // #if defined(ECB) && (ECB == 1) - - - - - -#if defined(CBC) && (CBC == 1) - - -static void XorWithIv(uint8_t* buf, const uint8_t* Iv) -{ - uint8_t i; - for (i = 0; i < AES_BLOCKLEN; ++i) { // The block in AES is always 128bit no matter the key size - buf[i] ^= Iv[i]; - } -} - -void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length) -{ - uintptr_t i; - uint8_t *Iv = ctx->Iv; - for (i = 0; i < length; i += AES_BLOCKLEN) { - XorWithIv(buf, Iv); - Cipher((state_t*)buf, ctx->RoundKey); - Iv = buf; - buf += AES_BLOCKLEN; - //printf("Step %d - %d", i/16, i); - } - /* store Iv in ctx for next call */ - memcpy(ctx->Iv, Iv, AES_BLOCKLEN); -} - -void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) -{ - uintptr_t i; - uint8_t storeNextIv[AES_BLOCKLEN]; - for (i = 0; i < length; i += AES_BLOCKLEN) { - memcpy(storeNextIv, buf, AES_BLOCKLEN); - InvCipher((state_t*)buf, ctx->RoundKey); - XorWithIv(buf, ctx->Iv); - memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); - buf += AES_BLOCKLEN; - } - -} - -#endif // #if defined(CBC) && (CBC == 1) - - - -#if defined(CTR) && (CTR == 1) - -/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ -void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) -{ - uint8_t buffer[AES_BLOCKLEN]; - - unsigned i; - int bi; - for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) { - if (bi == AES_BLOCKLEN) { /* we need to regen xor compliment in buffer */ - - memcpy(buffer, ctx->Iv, AES_BLOCKLEN); - Cipher((state_t*)buffer, ctx->RoundKey); - - /* Increment Iv and handle overflow */ - for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) { - /* inc will overflow */ - if (ctx->Iv[bi] == 255) { - ctx->Iv[bi] = 0; - continue; - } - ctx->Iv[bi] += 1; - break; - } - bi = 0; - } - - buf[i] = (buf[i] ^ buffer[bi]); - } -} - -#endif // #if defined(CTR) && (CTR == 1) diff --git a/lib/MySensors/hal/crypto/AVR/drivers/AES/aes.h b/lib/MySensors/hal/crypto/AVR/drivers/AES/aes.h deleted file mode 100644 index 294e321e..00000000 --- a/lib/MySensors/hal/crypto/AVR/drivers/AES/aes.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* AES implementation: https://github.com/kokke/tiny-AES-c -*/ - -#ifndef _AES_H_ -#define _AES_H_ - -// #define the macros below to 1/0 to enable/disable the mode of operation. -// -// CBC enables AES encryption in CBC-mode of operation. -// CTR enables encryption in counter-mode. -// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. - -// The #ifndef-guard allows it to be configured before #include'ing or at compile time. -#ifndef CBC -#define CBC 1 -#endif - -#ifndef ECB -#define ECB 0 -#endif - -#ifndef CTR -#define CTR 0 -#endif - - -#define AES128 1 -//#define AES192 1 -//#define AES256 1 - -#define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only - -#if defined(AES256) && (AES256 == 1) -#define AES_KEYLEN 32 -#define AES_keyExpSize 240 -#elif defined(AES192) && (AES192 == 1) -#define AES_KEYLEN 24 -#define AES_keyExpSize 208 -#else -#define AES_KEYLEN 16 // Key length in bytes -#define AES_keyExpSize 176 -#endif - -/** - * @brief AES state structure - */ -struct AES_ctx { - uint8_t RoundKey[AES_keyExpSize]; //!< RoundKey -#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) - uint8_t Iv[AES_BLOCKLEN]; //!< Iv -#endif -}; - -void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); -#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) -void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); -void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); -#endif - -#if defined(ECB) && (ECB == 1) -// buffer size is exactly AES_BLOCKLEN bytes; -// you need only AES_init_ctx as IV is not used in ECB -// NB: ECB is considered insecure for most uses -void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); -void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); - -#endif // #if defined(ECB) && (ECB == !) - - -#if defined(CBC) && (CBC == 1) -// buffer size MUST be mutile of AES_BLOCKLEN; -// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme -// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() -// no IV should ever be reused with the same key -void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); -void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); - -#endif // #if defined(CBC) && (CBC == 1) - - -#if defined(CTR) && (CTR == 1) - -// Same function for encrypting as for decrypting. -// IV is incremented for every block, and used after encryption as XOR-compliment for output -// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme -// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() -// no IV should ever be reused with the same key -void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); - -#endif // #if defined(CTR) && (CTR == 1) - - -#endif //_AES_H_ diff --git a/lib/MySensors/hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.cpp b/lib/MySensors/hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.cpp deleted file mode 100644 index f2bc6c2d..00000000 --- a/lib/MySensors/hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -*/ - -#include "hmac_sha256.h" - -/* -* all lengths in bits! -*/ -void hmac_sha256(void *dest, const void *key, uint16_t keylength_b, const void *msg, - uint32_t msglength_b) -{ - sha256_ctx_t s; - uint8_t buffer[HMAC_SHA256_BLOCK_BYTES]; - - (void)memset((void *)buffer, 0x00, HMAC_SHA256_BLOCK_BYTES); - - /* if key is larger than a block we have to hash it*/ - if (keylength_b > SHA256_BLOCK_BITS) { - sha256((sha256_hash_t *)buffer, key, keylength_b); - } else { - (void)memcpy((void *)buffer, (const void *)key, (keylength_b + 7) / 8); - } - - for (uint8_t i = 0; i < SHA256_BLOCK_BYTES; ++i) { - buffer[i] ^= IPAD; - } - sha256_init(&s); - sha256_nextBlock(&s, buffer); - while (msglength_b >= HMAC_SHA256_BLOCK_BITS) { - sha256_nextBlock(&s, msg); - msg = (uint8_t *)msg + HMAC_SHA256_BLOCK_BYTES; - msglength_b -= HMAC_SHA256_BLOCK_BITS; - } - sha256_lastBlock(&s, msg, msglength_b); - /* since buffer still contains key xor ipad we can do ... */ - for (uint8_t i = 0; i < HMAC_SHA256_BLOCK_BYTES; ++i) { - buffer[i] ^= IPAD ^ OPAD; - } - sha256_ctx2hash((sha256_hash_t *)dest, &s); /* save inner hash temporary to dest */ - sha256_init(&s); - sha256_nextBlock(&s, buffer); - sha256_lastBlock(&s, dest, SHA256_HASH_BITS); - sha256_ctx2hash((sha256_hash_t *)dest, &s); -} diff --git a/lib/MySensors/hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.h b/lib/MySensors/hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.h deleted file mode 100644 index 4e5ae80a..00000000 --- a/lib/MySensors/hal/crypto/AVR/drivers/HMAC_SHA256/hmac_sha256.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* ====================================================================== -* -* HMAC SHA256 implementation for AVR: -* -* This file is part of the AVR-Crypto-Lib. -* Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org) -* -* 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 . -* -* Author: Daniel Otte -* -* License: GPLv3 or later -* -* ====================================================================== -*/ - - -#ifndef _HMAC_SHA256_ -#define _HMAC_SHA256_ - -#define IPAD 0x36 //!< HMAC, inner hash, xor byte -#define OPAD 0x5C //!< HMAC, outer hash, xor byte - -#define HMAC_SHA256_BITS SHA256_HASH_BITS //!< Defines the size of a SHA-256 HMAC hash value in bits -#define HMAC_SHA256_BYTES SHA256_HASH_BYTES //!< Defines the size of a SHA-256 HMAC hash value in bytes -#define HMAC_SHA256_BLOCK_BITS SHA256_BLOCK_BITS //!< Defines the size of a SHA-256 HMAC input block in bits -#define HMAC_SHA256_BLOCK_BYTES SHA256_BLOCK_BYTES //!< Defines the size of a SHA-256 HMAC input block in bytes - -/** -* @brief hash context structure -*/ -typedef struct { - sha256_ctx_t a; //!< a - sha256_ctx_t b; //!< b -} hmac_sha256_ctx_t; - -/** -* @brief SHA256 HMAC function -* -* @param dest pointer to the location where the hash value is going to be written to -* @param key pointer to the key that's is needed for the HMAC calculation -* @param keylength_b length of the key -* @param msg pointer to the message that's going to be hashed -* @param msglength_b length of the message -*/ -void hmac_sha256(void *dest, const void *key, uint16_t keylength_b, const void *msg, - uint32_t msglength_b); - -#endif diff --git a/lib/MySensors/hal/crypto/AVR/drivers/SHA256/SHA256.S b/lib/MySensors/hal/crypto/AVR/drivers/SHA256/SHA256.S deleted file mode 100644 index d591dfb2..00000000 --- a/lib/MySensors/hal/crypto/AVR/drivers/SHA256/SHA256.S +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * This file is part of the AVR-Crypto-Lib. - * Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org) - * - * 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 . - * - * Author: Daniel Otte - * - * License: GPLv3 or later - */ -; sha-256 implementation in assembler -SHA256_BLOCK_BITS = 512 -SHA256_HASH_BITS = 256 - - -.macro precall - /* push r18 - r27, r30 - r31*/ - push r0 - push r1 - push r18 - push r19 - push r20 - push r21 - push r22 - push r23 - push r24 - push r25 - push r26 - push r27 - push r30 - push r31 - clr r1 -.endm - -.macro postcall - pop r31 - pop r30 - pop r27 - pop r26 - pop r25 - pop r24 - pop r23 - pop r22 - pop r21 - pop r20 - pop r19 - pop r18 - pop r1 - pop r0 -.endm - - -.macro hexdump length - push r27 - push r26 - ldi r25, '\r' - mov r24, r25 - call uart_putc - ldi r25, '\n' - mov r24, r25 - call uart_putc - pop r26 - pop r27 - movw r24, r26 -.if \length > 16 - ldi r22, lo8(16) - ldi r23, hi8(16) - push r27 - push r26 - call uart_hexdump - pop r26 - pop r27 - adiw r26, 16 - hexdump \length-16 -.else - ldi r22, lo8(\length) - ldi r23, hi8(\length) - call uart_hexdump -.endif -.endm - -/* X points to Block */ -.macro dbg_hexdump length - precall - hexdump \length - postcall -.endm - -.section .text - -SPL = 0x3D -SPH = 0x3E -SREG = 0x3F - - -; -;sha256_ctx_t is: -; -; [h0][h1][h2][h3][h4][h5][h6][h7][length] -; hn is 32 bit large, length is 64 bit large - -;########################################################### - -.global sha256_ctx2hash -; === sha256_ctx2hash === -; this function converts a state into a normal hash (bytestring) -; param1: the 16-bit destination pointer -; given in r25,r24 (r25 is most significant) -; param2: the 16-bit pointer to sha256_ctx structure -; given in r23,r22 -sha256_ctx2hash: - movw r26, r22 - movw r30, r24 - ldi r21, 8 - sbiw r26, 4 -1: - ldi r20, 4 - adiw r26, 8 -2: - ld r0, -X - st Z+, r0 - dec r20 - brne 2b - - dec r21 - brne 1b - - ret - -;########################################################### - -.global sha256 -; === sha256 === -; this function calculates SHA-256 hashes from messages in RAM -; param1: the 16-bit hash destination pointer -; given in r25,r24 (r25 is most significant) -; param2: the 16-bit pointer to message -; given in r23,r22 -; param3: 32-bit length value (length of message in bits) -; given in r21,r20,r19,r18 -sha256: -sha256_prolog: - push r8 - push r9 - push r10 - push r11 - push r12 - push r13 - push r16 - push r17 - in r30, SPL - in r31, SPH - sbiw r30, 8*4+8 - in r0, SREG - cli - out SPL, r30 - out SREG, r0 - out SPH, r31 - - push r25 - push r24 - adiw r30, 1 - movw r16, r30 - movw r8, r18 /* backup of length*/ - movw r10, r20 - - movw r12, r22 /* backup pf msg-ptr */ - - movw r24, r16 - rcall sha256_init - /* if length > 0xffff */ -1: - tst r11 - brne 2f - tst r10 - breq 4f -2: - movw r24, r16 - movw r22, r12 - rcall sha256_nextBlock - ldi r19, 64 - add r12, r19 - adc r13, r1 - /* length -= 512 */ - ldi r19, 0x02 - sub r9, r19 - sbc r10, r1 - sbc r11, r1 - rjmp 1b - -4: - movw r24, r16 - movw r22, r12 - movw r20, r8 - rcall sha256_lastBlock - - pop r24 - pop r25 - movw r22, r16 - rcall sha256_ctx2hash - -sha256_epilog: - in r30, SPL - in r31, SPH - adiw r30, 8*4+8 - in r0, SREG - cli - out SPL, r30 - out SREG, r0 - out SPH, r31 - pop r17 - pop r16 - pop r13 - pop r12 - pop r11 - pop r10 - pop r9 - pop r8 - ret - -;########################################################### - - -; block MUST NOT be larger than 64 bytes - -.global sha256_lastBlock -; === sha256_lastBlock === -; this function does padding & Co. for calculating SHA-256 hashes -; param1: the 16-bit pointer to sha256_ctx structure -; given in r25,r24 (r25 is most significant) -; param2: an 16-bit pointer to 64 byte block to hash -; given in r23,r22 -; param3: an 16-bit integer specifing length of block in bits -; given in r21,r20 -sha256_lastBlock_localSpace = (SHA256_BLOCK_BITS/8+1) - - -sha256_lastBlock: - cpi r21, 0x02 - brlo sha256_lastBlock_prolog - push r25 - push r24 - push r23 - push r22 - push r21 - push r20 - rcall sha256_nextBlock - pop r20 - pop r21 - pop r22 - pop r23 - pop r24 - pop r25 - subi r21, 0x02 - ldi r19, 64 - add r22, r19 - adc r23, r1 - rjmp sha256_lastBlock -sha256_lastBlock_prolog: - /* allocate space on stack */ - in r30, SPL - in r31, SPH - in r0, SREG - subi r30, lo8(64) - sbci r31, hi8(64) - cli - out SPL, r30 - out SREG,r0 - out SPH, r31 - - adiw r30, 1 /* SP points to next free byte on stack */ - mov r18, r20 /* r20 = LSB(length) */ - lsr r18 - lsr r18 - lsr r18 - bst r21, 0 /* may be we should explain this ... */ - bld r18, 5 /* now: r18 == length/8 (aka. length in bytes) */ - - - movw r26, r22 /* X points to begin of msg */ - tst r18 - breq sha256_lastBlock_post_copy - mov r1, r18 -sha256_lastBlock_copy_loop: - ld r0, X+ - st Z+, r0 - dec r1 - brne sha256_lastBlock_copy_loop -sha256_lastBlock_post_copy: -sha256_lastBlock_insert_stuffing_bit: - ldi r19, 0x80 - mov r0,r19 - ldi r19, 0x07 - and r19, r20 /* if we are in bitmode */ - breq 2f /* no bitmode */ -1: - lsr r0 - dec r19 - brne 1b - ld r19, X -/* maybe we should do some ANDing here, just for safety */ - or r0, r19 -2: - st Z+, r0 - inc r18 - -/* checking stuff here */ - cpi r18, 64-8+1 - brsh 0f - rjmp sha256_lastBlock_insert_zeros -0: - /* oh shit, we landed here */ - /* first we have to fill it up with zeros */ - ldi r19, 64 - sub r19, r18 - breq 2f -1: - st Z+, r1 - dec r19 - brne 1b -2: - sbiw r30, 63 - sbiw r30, 1 - movw r22, r30 - - push r31 - push r30 - push r25 - push r24 - push r21 - push r20 - rcall sha256_nextBlock - pop r20 - pop r21 - pop r24 - pop r25 - pop r30 - pop r31 - - /* now we should subtract 512 from length */ - movw r26, r24 - adiw r26, 4*8+1 /* we can skip the lowest byte */ - ld r19, X - subi r19, hi8(512) - st X+, r19 - ldi r18, 6 -1: - ld r19, X - sbci r19, 0 - st X+, r19 - dec r18 - brne 1b - -; clr r18 /* not neccessary ;-) */ - /* reset Z pointer to begin of block */ - -sha256_lastBlock_insert_zeros: - ldi r19, 64-8 - sub r19, r18 - breq sha256_lastBlock_insert_length - clr r1 -1: - st Z+, r1 /* r1 is still zero */ - dec r19 - brne 1b - -; rjmp sha256_lastBlock_epilog -sha256_lastBlock_insert_length: - movw r26, r24 /* X points to state */ - adiw r26, 8*4 /* X points to (state.length) */ - adiw r30, 8 /* Z points one after the last byte of block */ - ld r0, X+ - add r0, r20 - st -Z, r0 - ld r0, X+ - adc r0, r21 - st -Z, r0 - ldi r19, 6 -1: - ld r0, X+ - adc r0, r1 - st -Z, r0 - dec r19 - brne 1b - - sbiw r30, 64-8 - movw r22, r30 - rcall sha256_nextBlock - -sha256_lastBlock_epilog: - in r30, SPL - in r31, SPH - in r0, SREG - adiw r30, 63 ; lo8(64) - adiw r30, 1 ; hi8(64) - cli - out SPL, r30 - out SREG,r0 - out SPH, r31 - clr r1 - ret - -/**/ -;########################################################### - -.global sha256_nextBlock -; === sha256_nextBlock === -; this is the core function for calculating SHA-256 hashes -; param1: the 16-bit pointer to sha256_ctx structure -; given in r25,r24 (r25 is most significant) -; param2: an 16-bit pointer to 64 byte block to hash -; given in r23,r22 -sha256_nextBlock_localSpace = (64+8)*4 ; 64 32-bit values for w array and 8 32-bit values for a array (total 288 byte) - -Bck1 = 12 -Bck2 = 13 -Bck3 = 14 -Bck4 = 15 -Func1 = 22 -Func2 = 23 -Func3 = 24 -Func4 = 25 -Accu1 = 16 -Accu2 = 17 -Accu3 = 18 -Accu4 = 19 -XAccu1 = 8 -XAccu2 = 9 -XAccu3 = 10 -XAccu4 = 11 -T1 = 4 -T2 = 5 -T3 = 6 -T4 = 7 -LoopC = 1 -/* byteorder: high number <--> high significance */ -sha256_nextBlock: - ; initial, let's make some space ready for local vars - push r4 /* replace push & pop by mem ops? */ - push r5 - push r6 - push r7 - push r8 - push r9 - push r10 - push r11 - push r12 - push r13 - push r14 - push r15 - push r16 - push r17 - push r28 - push r29 - in r20, SPL - in r21, SPH - movw r18, r20 ;backup SP -; movw r26, r20 ; X points to free space on stack - movw r30, r22 ; Z points to message - subi r20, lo8(sha256_nextBlock_localSpace) ;sbiw can do only up to 63 - sbci r21, hi8(sha256_nextBlock_localSpace) - movw r26, r20 ; X points to free space on stack - in r0, SREG - cli ; we want to be uninterrupted while updating SP - out SPL, r20 - out SREG, r0 - out SPH, r21 - push r18 - push r19 - push r24 - push r25 /* param1 will be needed later */ - ; now we fill the w array with message (think about endianess) - adiw r26, 1 ; X++ - ldi r20, 16 -sha256_nextBlock_wcpyloop: - ld r23, Z+ - ld r22, Z+ - ld r19, Z+ - ld r18, Z+ - st X+, r18 - st X+, r19 - st X+, r22 - st X+, r23 - dec r20 - brne sha256_nextBlock_wcpyloop -/* for (i=16; i<64; ++i){ - w[i] = SIGMA_b(w[i-2]) + w[i-7] + SIGMA_a(w[i-15]) + w[i-16]; - } */ - /* r25,r24,r23,r24 (r21,r20) are function values - r19,r18,r17,r16 are the accumulator - r15,r14,r13,rBck1 are backup1 - r11,r10,r9 ,r8 are xor accu - r1 is round counter */ - - ldi r20, 64-16 - mov LoopC, r20 -sha256_nextBlock_wcalcloop: - movw r30, r26 ; cp X to Z - sbiw r30, 63 - sbiw r30, 1 ; substract 64 = 16*4 - ld Accu1, Z+ - ld Accu2, Z+ - ld Accu3, Z+ - ld Accu4, Z+ /* w[i] = w[i-16] */ - ld Bck1, Z+ - ld Bck2, Z+ - ld Bck3, Z+ - ld Bck4, Z+ /* backup = w[i-15] */ - /* now sigma 0 */ - mov Func1, Bck2 - mov Func2, Bck3 - mov Func3, Bck4 - mov Func4, Bck1 /* prerotated by 8 */ - ldi r20, 1 - rcall bitrotl - movw XAccu1, Func1 - movw XAccu3, Func3 /* store ROTR(w[i-15],7) in xor accu */ - movw Func1, Bck3 - movw Func3, Bck1 /* prerotated by 16 */ - ldi r20, 2 - rcall bitrotr - eor XAccu1, Func1 /* xor ROTR(w[i-15], 18)*/ - eor XAccu2, Func2 - eor XAccu3, Func3 - eor XAccu4, Func4 - ldi Func2, 3 /* now shr3 */ /*we can destroy backup now*/ -sigma0_shr: - lsr Bck4 - ror Bck3 - ror Bck2 - ror Bck1 - dec Func2 - brne sigma0_shr - eor XAccu1, Bck1 - eor XAccu2, Bck2 - eor XAccu3, Bck3 - eor XAccu4, Bck4 /* xor SHR(w[i-15], 3)*/ /* xor accu == sigma1(w[i-15]) */ - add Accu1, XAccu1 - adc Accu2, XAccu2 - adc Accu3, XAccu3 - adc Accu4, XAccu4 /* finished with sigma0 */ - ldd Func1, Z+7*4 /* now accu += w[i-7] */ - ldd Func2, Z+7*4+1 - ldd Func3, Z+7*4+2 - ldd Func4, Z+7*4+3 - add Accu1, Func1 - adc Accu2, Func2 - adc Accu3, Func3 - adc Accu4, Func4 - ldd Bck1, Z+12*4 /* now backup = w[i-2]*/ - ldd Bck2, Z+12*4+1 - ldd Bck3, Z+12*4+2 - ldd Bck4, Z+12*4+3 - /* now sigma 1 */ - movw Func1, Bck3 - movw Func3, Bck1 /* prerotated by 16 */ - ldi r20, 1 - rcall bitrotr - movw XAccu3, Func3 - movw XAccu1, Func1 /* store in ROTR(w[i-2], 17) xor accu */ -; movw Func1, Bck3 -; movw Func3, Bck1 /* prerotated by 16 */ - ldi r20, 2 - rcall bitrotr - eor XAccu1, Func1 /* xor ROTR(w[i-2], 19)*/ - eor XAccu2, Func2 - eor XAccu3, Func3 - eor XAccu4, Func4 - ldi Func2, 2 /* now shr10 (dirty trick, skipping a byte) */ /*we can destroy backup now*/ -sigma1_shr: - lsr Bck4 - ror Bck3 - ror Bck2 - dec Func2 - brne sigma1_shr - eor XAccu1, Bck2 - eor XAccu2, Bck3 - eor XAccu3, Bck4 /* xor SHR(w[i-2], 10)*/ /* xor accu == sigma1(w[i-15]) */ - add Accu1, XAccu1 - adc Accu2, XAccu2 - adc Accu3, XAccu3 - adc Accu4, XAccu4 /* finished with sigma0 */ - /* now let's store the shit */ - st X+, Accu1 - st X+, Accu2 - st X+, Accu3 - st X+, Accu4 - dec LoopC - breq 3f ; skip if zero - rjmp sha256_nextBlock_wcalcloop -3: - /* we are finished with w array X points one byte post w */ -/* init a array */ - pop r31 - pop r30 - push r30 - push r31 - ldi r25, 8*4 /* 8 32-bit values to copy from ctx to a array */ -init_a_array: - ld r1, Z+ - st X+, r1 - dec r25 - brne init_a_array - -/* now the real fun begins */ -/* for (i=0; i<64; ++i){ - t1 = a[7] + SIGMA1(a[4]) + CH(a[4],a[5],a[6]) + k[i] + w[i]; - t2 = SIGMA0(a[0]) + MAJ(a[0],a[1],a[2]); - memmove(&(a[1]), &(a[0]), 7*4); // a[7]=a[6]; a[6]=a[5]; a[5]=a[4]; a[4]=a[3]; a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; - a[4] += t1; - a[0] = t1 + t2; - } */ - /* Y points to a[0], Z ('cause lpm wants it) points to k[i], X points to w[i] */ - sbiw r26, 8*4 /* X still points at a[7]+1*/ - movw r28, r26 - ldi r30, lo8(sha256_kv) - ldi r31, hi8(sha256_kv) - dec r27 /* X - (64*4 == 256) */ - ldi r25, 64 - mov LoopC, r25 -sha256_main_loop: - /* now calculate t1 */ - /*CH(x,y,z) = (x&y)^((~x)&z)*/ - ldd T1, Y+5*4 - ldd T2, Y+5*4+1 - ldd T3, Y+5*4+2 - ldd T4, Y+5*4+3 /* y in T */ - ldd Func1, Y+4*4 - ldd Func2, Y+4*4+1 - ldd Func3, Y+4*4+2 - ldd Func4, Y+4*4+3 /* x in Func */ - ldd Bck1, Y+6*4 - ldd Bck2, Y+6*4+1 - ldd Bck3, Y+6*4+2 - ldd Bck4, Y+6*4+3 /* z in Bck */ - and T1, Func1 - and T2, Func2 - and T3, Func3 - and T4, Func4 - com Func1 - com Func2 - com Func3 - com Func4 - and Bck1, Func1 - and Bck2, Func2 - and Bck3, Func3 - and Bck4, Func4 - eor T1, Bck1 - eor T2, Bck2 - eor T3, Bck3 - eor T4, Bck4 /* done, CH(x,y,z) is in T */ - /* now SIGMA1(a[4]) */ - ldd Bck4, Y+4*4 /* think about using it from Func reg above*/ - ldd Bck1, Y+4*4+1 - ldd Bck2, Y+4*4+2 - ldd Bck3, Y+4*4+3 /* load prerotate by 8-bit */ - movw Func1, Bck1 - movw Func3, Bck3 - ldi r20, 2 - rcall bitrotl /* rotr(x,6) */ - movw XAccu1, Func1 - movw XAccu3, Func3 - movw Func1, Bck1 - movw Func3, Bck3 - ldi r20, 3 - rcall bitrotr /* rotr(x,11) */ - eor XAccu1, Func1 - eor XAccu2, Func2 - eor XAccu3, Func3 - eor XAccu4, Func4 - movw Func1, Bck3 /* this prerotates furteh 16 bits*/ - movw Func3, Bck1 /* so we have now prerotated by 24 bits*/ - ldi r20, 1 - rcall bitrotr /* rotr(x,11) */ - eor XAccu1, Func1 - eor XAccu2, Func2 - eor XAccu3, Func3 - eor XAccu4, Func4 /* finished with SIGMA1, add it to T */ - add T1, XAccu1 - adc T2, XAccu2 - adc T3, XAccu3 - adc T4, XAccu4 - /* now we've to add a[7], w[i] and k[i] */ - ldd XAccu1, Y+4*7 - ldd XAccu2, Y+4*7+1 - ldd XAccu3, Y+4*7+2 - ldd XAccu4, Y+4*7+3 - add T1, XAccu1 - adc T2, XAccu2 - adc T3, XAccu3 - adc T4, XAccu4 /* add a[7] */ - ld XAccu1, X+ - ld XAccu2, X+ - ld XAccu3, X+ - ld XAccu4, X+ - add T1, XAccu1 - adc T2, XAccu2 - adc T3, XAccu3 - adc T4, XAccu4 /* add w[i] */ - lpm XAccu1, Z+ - lpm XAccu2, Z+ - lpm XAccu3, Z+ - lpm XAccu4, Z+ - add T1, XAccu1 - adc T2, XAccu2 - adc T3, XAccu3 - adc T4, XAccu4 /* add k[i] */ /* finished with t1 */ - /*now t2 = SIGMA0(a[0]) + MAJ(a[0],a[1],a[2]) */ /*i did to much x86 asm, i always see 4 32bit regs*/ - /* starting with MAJ(x,y,z) */ - ldd Func1, Y+4*0+0 - ldd Func2, Y+4*0+1 - ldd Func3, Y+4*0+2 - ldd Func4, Y+4*0+3 /* load x=a[0] */ - ldd XAccu1, Y+4*1+0 - ldd XAccu2, Y+4*1+1 - ldd XAccu3, Y+4*1+2 - ldd XAccu4, Y+4*1+3 /* load y=a[1] */ - and XAccu1, Func1 - and XAccu2, Func2 - and XAccu3, Func3 - and XAccu4, Func4 /* XAccu == (x & y) */ - ldd Bck1, Y+4*2+0 - ldd Bck2, Y+4*2+1 - ldd Bck3, Y+4*2+2 - ldd Bck4, Y+4*2+3 /* load z=a[2] */ - and Func1, Bck1 - and Func2, Bck2 - and Func3, Bck3 - and Func4, Bck4 - eor XAccu1, Func1 - eor XAccu2, Func2 - eor XAccu3, Func3 - eor XAccu4, Func4 /* XAccu == (x & y) ^ (x & z) */ - ldd Func1, Y+4*1+0 - ldd Func2, Y+4*1+1 - ldd Func3, Y+4*1+2 - ldd Func4, Y+4*1+3 /* load y=a[1] */ - and Func1, Bck1 - and Func2, Bck2 - and Func3, Bck3 - and Func4, Bck4 - eor XAccu1, Func1 - eor XAccu2, Func2 - eor XAccu3, Func3 - eor XAccu4, Func4 /* XAccu == Maj(x,y,z) == (x & y) ^ (x & z) ^ (y & z) */ - /* SIGMA0(a[0]) */ - ldd Bck1, Y+4*0+0 /* we should combine this with above */ - ldd Bck2, Y+4*0+1 - ldd Bck3, Y+4*0+2 - ldd Bck4, Y+4*0+3 - movw Func1, Bck1 - movw Func3, Bck3 - ldi r20, 2 - rcall bitrotr - movw Accu1, Func1 - movw Accu3, Func3 /* Accu = shr(a[0], 2) */ - movw Func1, Bck3 - movw Func3, Bck1 /* prerotate by 16 bits */ - ldi r20, 3 - rcall bitrotl - eor Accu1, Func1 - eor Accu2, Func2 - eor Accu3, Func3 - eor Accu4, Func4 /* Accu ^= shr(a[0], 13) */ - mov Func1, Bck4 - mov Func2, Bck1 - mov Func3, Bck2 - mov Func4, Bck3 /* prerotate by 24 bits */ - ldi r20, 2 - rcall bitrotl - eor Accu1, Func1 - eor Accu2, Func2 - eor Accu3, Func3 - eor Accu4, Func4 /* Accu ^= shr(a[0], 22) */ - add Accu1, XAccu1 /* add previous result (MAJ)*/ - adc Accu2, XAccu2 - adc Accu3, XAccu3 - adc Accu4, XAccu4 - /* now we are finished with the computing stuff (t1 in T, t2 in Accu)*/ - /* a[7]=a[6]; a[6]=a[5]; a[5]=a[4]; a[4]=a[3]; a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; */ - - ldi r21, 7*4 - adiw r28, 7*4 -a_shift_loop: - ld r25, -Y /* warning: this is PREdecrement */ - std Y+4, r25 - dec r21 - brne a_shift_loop - - ldd Bck1, Y+4*4+0 - ldd Bck2, Y+4*4+1 - ldd Bck3, Y+4*4+2 - ldd Bck4, Y+4*4+3 - add Bck1, T1 - adc Bck2, T2 - adc Bck3, T3 - adc Bck4, T4 - std Y+4*4+0, Bck1 - std Y+4*4+1, Bck2 - std Y+4*4+2, Bck3 - std Y+4*4+3, Bck4 - add Accu1, T1 - adc Accu2, T2 - adc Accu3, T3 - adc Accu4, T4 - std Y+4*0+0, Accu1 - std Y+4*0+1, Accu2 - std Y+4*0+2, Accu3 - std Y+4*0+3, Accu4 /* a array updated */ - - - dec LoopC - breq update_state - rjmp sha256_main_loop ;brne sha256_main_loop -update_state: - /* update state */ - /* pointers to state should still exist on the stack ;-) */ - pop r31 - pop r30 - ldi r21, 8 -update_state_loop: - ldd Accu1, Z+0 - ldd Accu2, Z+1 - ldd Accu3, Z+2 - ldd Accu4, Z+3 - ld Func1, Y+ - ld Func2, Y+ - ld Func3, Y+ - ld Func4, Y+ - add Accu1, Func1 - adc Accu2, Func2 - adc Accu3, Func3 - adc Accu4, Func4 - st Z+, Accu1 - st Z+, Accu2 - st Z+, Accu3 - st Z+, Accu4 - dec r21 - brne update_state_loop - /* now we just have to update the length */ - adiw r30, 1 /* since we add 512, we can simply skip the LSB */ - ldi r21, 2 - ldi r22, 6 - ld r20, Z - add r20, r21 - st Z+, r20 - clr r21 -sha256_nextBlock_fix_length: - brcc sha256_nextBlock_epilog - ld r20, Z - adc r20, r21 - st Z+, r20 - dec r22 - brne sha256_nextBlock_fix_length - -; EPILOG -sha256_nextBlock_epilog: -/* now we should clean up the stack */ - - pop r21 - pop r20 - in r0, SREG - cli ; we want to be uninterrupted while updating SP - out SPL, r20 - out SREG, r0 - out SPH, r21 - clr r1 - pop r29 - pop r28 - pop r17 - pop r16 - pop r15 - pop r14 - pop r13 - pop r12 - pop r11 - pop r10 - pop r9 - pop r8 - pop r7 - pop r6 - pop r5 - pop r4 - ret - -sha256_kv: ; round-key-vector stored in ProgMem -.word 0x2f98, 0x428a, 0x4491, 0x7137, 0xfbcf, 0xb5c0, 0xdba5, 0xe9b5, 0xc25b, 0x3956, 0x11f1, 0x59f1, 0x82a4, 0x923f, 0x5ed5, 0xab1c -.word 0xaa98, 0xd807, 0x5b01, 0x1283, 0x85be, 0x2431, 0x7dc3, 0x550c, 0x5d74, 0x72be, 0xb1fe, 0x80de, 0x06a7, 0x9bdc, 0xf174, 0xc19b -.word 0x69c1, 0xe49b, 0x4786, 0xefbe, 0x9dc6, 0x0fc1, 0xa1cc, 0x240c, 0x2c6f, 0x2de9, 0x84aa, 0x4a74, 0xa9dc, 0x5cb0, 0x88da, 0x76f9 -.word 0x5152, 0x983e, 0xc66d, 0xa831, 0x27c8, 0xb003, 0x7fc7, 0xbf59, 0x0bf3, 0xc6e0, 0x9147, 0xd5a7, 0x6351, 0x06ca, 0x2967, 0x1429 -.word 0x0a85, 0x27b7, 0x2138, 0x2e1b, 0x6dfc, 0x4d2c, 0x0d13, 0x5338, 0x7354, 0x650a, 0x0abb, 0x766a, 0xc92e, 0x81c2, 0x2c85, 0x9272 -.word 0xe8a1, 0xa2bf, 0x664b, 0xa81a, 0x8b70, 0xc24b, 0x51a3, 0xc76c, 0xe819, 0xd192, 0x0624, 0xd699, 0x3585, 0xf40e, 0xa070, 0x106a -.word 0xc116, 0x19a4, 0x6c08, 0x1e37, 0x774c, 0x2748, 0xbcb5, 0x34b0, 0x0cb3, 0x391c, 0xaa4a, 0x4ed8, 0xca4f, 0x5b9c, 0x6ff3, 0x682e -.word 0x82ee, 0x748f, 0x636f, 0x78a5, 0x7814, 0x84c8, 0x0208, 0x8cc7, 0xfffa, 0x90be, 0x6ceb, 0xa450, 0xa3f7, 0xbef9, 0x78f2, 0xc671 - - -;########################################################### - -.global sha256_init -;uint32_t sha256_init_vector[]={ -; 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, -; 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 }; -; -;void sha256_init(sha256_ctx_t *state){ -; state->length=0; -; memcpy(state->h, sha256_init_vector, 8*4); -;} -; param1: (r23,r24) 16-bit pointer to sha256_ctx_t struct in ram -; modifys: Z(r30,r31), Func1, r22 -sha256_init: - movw r26, r24 ; (24,25) --> (26,27) load X with param1 - ldi r30, lo8((sha256_init_vector)) - ldi r31, hi8((sha256_init_vector)) - ldi r22, 32+8 -sha256_init_vloop: - lpm r23, Z+ - st X+, r23 - dec r22 - brne sha256_init_vloop - ret - -sha256_init_vector: -.word 0xE667, 0x6A09 -.word 0xAE85, 0xBB67 -.word 0xF372, 0x3C6E -.word 0xF53A, 0xA54F -.word 0x527F, 0x510E -.word 0x688C, 0x9B05 -.word 0xD9AB, 0x1F83 -.word 0xCD19, 0x5BE0 -.word 0x0000, 0x0000 -.word 0x0000, 0x0000 - -;########################################################### - -.global rotl32 -; === ROTL32 === -; function that rotates a 32 bit word to the left -; param1: the 32-bit word to rotate -; given in r25,r24,r23,r22 (r25 is most significant) -; param2: an 8-bit value telling how often to rotate -; given in r20 -; modifys: r21, r22 -rotl32: - cpi r20, 8 - brlo bitrotl - mov r21, r25 - mov r25, r24 - mov r24, r23 - mov r23, r22 - mov r22, r21 - subi r20, 8 - rjmp rotl32 -bitrotl: - clr r21 - clc -bitrotl_loop: - tst r20 - breq fixrotl -2: - rol r22 - rol r23 - rol r24 - rol r25 - rol r21 - dec r20 - brne 2b -fixrotl: - or r22, r21 - ret - - -;########################################################### - -.global rotr32 -; === ROTR32 === -; function that rotates a 32 bit word to the right -; param1: the 32-bit word to rotate -; given in r25,r24,r23,22 (r25 is most significant) -; param2: an 8-bit value telling how often to rotate -; given in r20 -; modifys: r21, r22 -rotr32: - cpi r20, 8 - brlo bitrotr - mov r21, r22 - mov r22, r23 - mov r23, r24 - mov r24, r25 - mov r25, r21 - subi r20, 8 - rjmp rotr32 -bitrotr: - clr r21 - clc -bitrotr_loop: - tst r20 - breq fixrotr -2: - ror r25 - ror r24 - ror r23 - ror r22 - ror r21 - dec r20 - brne 2b -fixrotr: - or r25, r21 - ret - - -;########################################################### - -.global change_endian32 -; === change_endian32 === -; function that changes the endianess of a 32-bit word -; param1: the 32-bit word -; given in r25,r24,r23,22 (r25 is most significant) -; modifys: r21, r22 -change_endian32: - movw r20, r22 ; (r22,r23) --> (r20,r21) - mov r22, r25 - mov r23, r24 - mov r24, r21 - mov r25, r20 - -;########################################################### diff --git a/lib/MySensors/hal/crypto/AVR/drivers/SHA256/sha256.cpp b/lib/MySensors/hal/crypto/AVR/drivers/SHA256/sha256.cpp deleted file mode 100644 index 89a01b4f..00000000 --- a/lib/MySensors/hal/crypto/AVR/drivers/SHA256/sha256.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* ====================================================================== -* -* SHA256 implementation for AVR: -* -* This file is part of the AVR-Crypto-Lib. -* Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org) -* -* 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 . -* -* Author: Daniel Otte -* -* License: GPLv3 or later -* -* ====================================================================== -*/ - -#include "sha256.h" diff --git a/lib/MySensors/hal/crypto/AVR/drivers/SHA256/sha256.h b/lib/MySensors/hal/crypto/AVR/drivers/SHA256/sha256.h deleted file mode 100644 index 8e275492..00000000 --- a/lib/MySensors/hal/crypto/AVR/drivers/SHA256/sha256.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* ====================================================================== -* -* SHA256 implementation for AVR: -* -* This file is part of the AVR-Crypto-Lib. -* Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org) -* -* 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 . -* -* Author: Daniel Otte -* -* License: GPLv3 or later -* -* ====================================================================== -*/ - -#ifndef _SHA256_H_ -#define _SHA256_H_ - -#define MY_CRYPTO_SHA256_ASM //!< Switch to define correct variable scope for ASM SHA256 implementation - -#define IPAD 0x36 //!< HMAC, inner hash, xor byte -#define OPAD 0x5C //!< HMAC, outer hash, xor byte - -#define SHA256_HASH_BITS 256 //!< Defines the size of a SHA-256 hash value in bits -#define SHA256_HASH_BYTES (SHA256_HASH_BITS/8) //!< Defines the size of a SHA-256 hash value in bytes -#define SHA256_BLOCK_BITS 512 //!< Defines the size of a SHA-256 input block in bits -#define SHA256_BLOCK_BYTES (SHA256_BLOCK_BITS/8) //!< Defines the size of a SHA-256 input block in bytes - -/** -* @brief SHA-256 context type -* -* A variable of this type may hold the state of a SHA-256 hashing process -*/ -typedef struct { - uint32_t h[8]; //!< h - uint64_t length; //!< length -} sha256_ctx_t; - -/** -* @brief SHA-256 hash value type -* -* A variable of this type may hold the hash value produced by the -* sha256_ctx2hash(sha256_hash_t *dest, const sha256_ctx_t *state) function. -*/ -typedef uint8_t sha256_hash_t[SHA256_HASH_BYTES]; - -extern "C" { // ASM implementation, see MyASM.S - /** - * @brief initialise a SHA-256 context - * - * This function sets a ::sha256_ctx_t to the initial values for hashing. - * @param state pointer to the SHA-256 hashing context - */ - void sha256_init(sha256_ctx_t *state); - - /** - * @brief update the context with a given block - * - * This function updates the SHA-256 hash context by processing the given block - * of fixed length. - * @param state pointer to the SHA-256 hash context - * @param block pointer to the block of fixed length (512 bit = 64 byte) - */ - void sha256_nextBlock(sha256_ctx_t *state, const void *block); - - /** - * @brief finalize the context with the given block - * - * This function finalizes the SHA-256 hash context by processing the given block - * of variable length. - * @param state pointer to the SHA-256 hash context - * @param block pointer to the block of fixed length (512 bit = 64 byte) - * @param length_b the length of the block in bits - */ - void sha256_lastBlock(sha256_ctx_t *state, const void *block, uint16_t length_b); - - /** - * @brief convert the hash state into the hash value - * - * This function reads the context and writes the hash value to the destination - * @param dest pointer to the location where the hash value should be written - * @param state pointer to the SHA-256 hash context - */ - void sha256_ctx2hash(sha256_hash_t *dest, const sha256_ctx_t *state); - - /** - * @brief simple SHA-256 hashing function for direct hashing - * - * This function automaticaly hashes a given message of arbitary length with - * the SHA-256 hashing algorithm. - * @param dest pointer to the location where the hash value is going to be written to - * @param msg pointer to the message thats going to be hashed - * @param length_b length of the message in bits - */ - void sha256(sha256_hash_t *dest, const void *msg, uint32_t length_b); -} - -#endif diff --git a/lib/MySensors/hal/crypto/ESP32/MyCryptoESP32.cpp b/lib/MySensors/hal/crypto/ESP32/MyCryptoESP32.cpp deleted file mode 100644 index 587a1353..00000000 --- a/lib/MySensors/hal/crypto/ESP32/MyCryptoESP32.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - -#include "MyCryptoESP32.h" - -// ESP32 SHA256 -void SHA256(uint8_t *dest, const uint8_t *data, size_t dataLength) -{ - mbedtls_md_context_t ctx; - mbedtls_md_init(&ctx); - mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, (const unsigned char *)data, dataLength); - mbedtls_md_finish(&ctx, dest); -} - - -// ESP32 SHA256HMAC -void SHA256HMAC(uint8_t *dest, const uint8_t *key, size_t keyLength, const uint8_t *data, - size_t dataLength) -{ - mbedtls_md_context_t ctx; - mbedtls_md_init(&ctx); - mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); - mbedtls_md_starts(&ctx); - mbedtls_md_hmac_starts(&ctx, (const unsigned char *)key, keyLength); - mbedtls_md_hmac_update(&ctx, (const unsigned char *)data, dataLength); - mbedtls_md_hmac_finish(&ctx, dest); -} - -// ESP32 AES128 CBC -static mbedtls_aes_context aes_ctx; - -void AES128CBCInit(const uint8_t *key) -{ - mbedtls_aes_init(&aes_ctx); - (void)mbedtls_aes_setkey_enc(&aes_ctx, key, 128); -} - -void AES128CBCEncrypt(uint8_t *iv, uint8_t *buffer, const size_t dataLength) -{ - mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, dataLength, iv, (const unsigned char *)buffer, - (unsigned char *)buffer); -} - -void AES128CBCDecrypt(uint8_t *iv, uint8_t *buffer, const size_t dataLength) -{ - mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, dataLength, iv, (const unsigned char *)buffer, - (unsigned char *)buffer); -} diff --git a/lib/MySensors/hal/crypto/ESP32/MyCryptoESP32.h b/lib/MySensors/hal/crypto/ESP32/MyCryptoESP32.h deleted file mode 100644 index bef76b21..00000000 --- a/lib/MySensors/hal/crypto/ESP32/MyCryptoESP32.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - -#ifndef MyCryptoESP32_h -#define MyCryptoESP32_h - -#include "hal/crypto/MyCryptoHAL.h" -#include "mbedtls/md.h" -#include "mbedtls/aes.h" - -#endif diff --git a/lib/MySensors/hal/crypto/MyCryptoHAL.h b/lib/MySensors/hal/crypto/MyCryptoHAL.h deleted file mode 100644 index fd3741ea..00000000 --- a/lib/MySensors/hal/crypto/MyCryptoHAL.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - -#ifndef MyCryptoHAL_h -#define MyCryptoHAL_h - -/** -* @brief SHA256 calculation -* -* The returned hash size is always 32 bytes. -* -* @param dest Buffer to return 32-byte hash. -* @param data Buffer with data to add. -* @param dataLength Size of data buffer. -*/ -void SHA256(uint8_t *dest, const uint8_t *data, size_t dataLength); - -/** -* @brief SHA256 HMAC calculation -* -* The returned hash size is always 32 bytes. -* -* @param dest Buffer to return 32-byte hash. -* @param key Buffer with HMAC key. -* @param keyLength Size of HMAC key. -* @param data Buffer with data to add. -* @param dataLength Size of data buffer. -*/ -void SHA256HMAC(uint8_t *dest, const uint8_t *key, size_t keyLength, const uint8_t *data, - size_t dataLength); - -/** -* @brief AES128CBCInit -* @param key AES encryption key, 16 bytes -*/ -void AES128CBCInit(const uint8_t *key); -/** -* @brief AES128CBCEncrypt -* @param iv Initialization vector, 16 bytes -* @param buffer Buffer to enctypt -* @param dataLength Buffer length -*/ -void AES128CBCEncrypt(uint8_t *iv, uint8_t *buffer, const size_t dataLength); -/** -* @brief AES128CBCDecrypt -* @param iv Initialization vector, 16 bytes -* @param buffer Buffer to decrypt -* @param dataLength Buffer length -*/ -void AES128CBCDecrypt(uint8_t *iv, uint8_t *buffer, const size_t dataLength); - -#endif diff --git a/lib/MySensors/hal/crypto/generic/MyCryptoGeneric.cpp b/lib/MySensors/hal/crypto/generic/MyCryptoGeneric.cpp deleted file mode 100644 index 4b24238b..00000000 --- a/lib/MySensors/hal/crypto/generic/MyCryptoGeneric.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - -#include "MyCryptoGeneric.h" - -void SHA256HMAC(uint8_t *dest, const uint8_t *key, size_t keyLength, const uint8_t *data, - size_t dataLength) -{ - SHA256HMACInit(key, keyLength); - SHA256HMACAdd(data, dataLength); - SHA256HMACResult(dest); -} - -AES _aes; - -void AES128CBCInit(const uint8_t *key) -{ - _aes.set_key((byte *)key, 16); -} - -void AES128CBCEncrypt(uint8_t *iv, uint8_t *buffer, const size_t dataLength) -{ - _aes.cbc_encrypt((byte *)buffer, (byte *)buffer, dataLength / 16, iv); -} - -void AES128CBCDecrypt(uint8_t *iv, uint8_t *buffer, const size_t dataLength) -{ - _aes.cbc_decrypt((byte *)buffer, (byte *)buffer, dataLength / 16, iv); -} diff --git a/lib/MySensors/hal/crypto/generic/MyCryptoGeneric.h b/lib/MySensors/hal/crypto/generic/MyCryptoGeneric.h deleted file mode 100644 index a10ee7a5..00000000 --- a/lib/MySensors/hal/crypto/generic/MyCryptoGeneric.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -*/ - -#ifndef MyCryptoGeneric_h -#define MyCryptoGeneric_h - -#include "hal/crypto/MyCryptoHAL.h" -#include "hal/crypto/generic/drivers/AES/AES.cpp" -#include "hal/crypto/generic/drivers/SHA256/sha256.cpp" -#include "hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.cpp" - -#endif diff --git a/lib/MySensors/hal/crypto/generic/drivers/AES/AES.cpp b/lib/MySensors/hal/crypto/generic/drivers/AES/AES.cpp deleted file mode 100644 index 5f35bb15..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/AES/AES.cpp +++ /dev/null @@ -1,631 +0,0 @@ -#include "AES.h" - -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The redistribution and use of this software (with or without changes) - is allowed without the payment of fees or royalties provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue 09/09/2006 - - This is an AES implementation that uses only 8-bit byte operations on the - cipher state (there are options to use 32-bit types if available). - - The combination of mix columns and byte substitution used here is based on - that developed by Karl Malbrain. His contribution is acknowledged. - */ - -/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down - and tailored to 8-bit microcontroller abilities and Arduino datatypes. - - The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all - the other transformations are coded to save table space. Many efficiency - improvments to the routines mix_sub_columns() and inv_mix_sub_columns() - (mainly common sub-expression elimination). - - Only the routines with precalculated subkey schedule are retained (together - with set_key() - this does however mean each AES object takes 240 bytes of - RAM, alas) - - The CBC routines side-effect the iv argument (so that successive calls work - together correctly). - - All the encryption and decryption routines work with plain == cipher for - in-place encryption, note. - -*/ - - -/* functions for finite field multiplication in the AES Galois field */ - -/* code was modified by george spanos - * 16/12/14 - */ - -// GF(2^8) stuff - -#define WPOLY 0x011B -#define DPOLY 0x008D - -const static byte s_fwd [0x100] PROGMEM = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, -} ; - -const static byte s_inv [0x100] PROGMEM = { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, -} ; - -// times 2 in the GF(2^8) -#define f2(x) (((x) & 0x80) ? (x << 1) ^ WPOLY : x << 1) -#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) - -static byte s_box (byte x) -{ - // return fwd_affine (pgm_read_byte (&inv [x])) ; - return pgm_read_byte (& s_fwd [x]) ; -} - -// Inverse Sbox -static byte is_box (byte x) -{ - // return pgm_read_byte (&inv [inv_affine (x)]) ; - return pgm_read_byte (& s_inv [x]) ; -} - - -static void xor_block (byte * d, byte * s) -{ - for (byte i = 0 ; i < N_BLOCK ; i += 4) { - *d++ ^= *s++ ; // some unrolling - *d++ ^= *s++ ; - *d++ ^= *s++ ; - *d++ ^= *s++ ; - } -} - -static void copy_and_key (byte * d, byte * s, byte * k) -{ - for (byte i = 0 ; i < N_BLOCK ; i += 4) { - *d++ = *s++ ^ *k++ ; // some unrolling - *d++ = *s++ ^ *k++ ; - *d++ = *s++ ^ *k++ ; - *d++ = *s++ ^ *k++ ; - } -} - -// #define add_round_key(d, k) xor_block (d, k) - -/* SUB ROW PHASE */ - -static void shift_sub_rows (byte st [N_BLOCK]) -{ - st [0] = s_box (st [0]) ; - st [4] = s_box (st [4]) ; - st [8] = s_box (st [8]) ; - st [12] = s_box (st [12]) ; - - byte tt = st [1] ; - st [1] = s_box (st [5]) ; - st [5] = s_box (st [9]) ; - st [9] = s_box (st [13]) ; - st [13] = s_box (tt) ; - - tt = st[2] ; - st [2] = s_box (st [10]) ; - st [10] = s_box (tt) ; - tt = st[6] ; - st [6] = s_box (st [14]) ; - st [14] = s_box (tt) ; - - tt = st[15] ; - st [15] = s_box (st [11]) ; - st [11] = s_box (st [7]) ; - st [7] = s_box (st [3]) ; - st [3] = s_box (tt) ; -} - -static void inv_shift_sub_rows (byte st[N_BLOCK]) -{ - st [0] = is_box (st[0]) ; - st [4] = is_box (st [4]); - st [8] = is_box (st[8]) ; - st [12] = is_box (st [12]); - - byte tt = st[13] ; - st [13] = is_box (st [9]) ; - st [9] = is_box (st [5]) ; - st [5] = is_box (st [1]) ; - st [1] = is_box (tt) ; - - tt = st [2] ; - st [2] = is_box (st [10]) ; - st [10] = is_box (tt) ; - tt = st [6] ; - st [6] = is_box (st [14]) ; - st [14] = is_box (tt) ; - - tt = st [3] ; - st [3] = is_box (st [7]) ; - st [7] = is_box (st [11]) ; - st [11] = is_box (st [15]) ; - st [15] = is_box (tt) ; -} - -/* SUB COLUMNS PHASE */ - -static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK]) -{ - byte j = 5 ; - byte k = 10 ; - byte l = 15 ; - for (byte i = 0 ; i < N_BLOCK ; i += N_COL) { - byte a = st [i] ; - byte b = st [j] ; - j = (j+N_COL) & 15 ; - byte c = st [k] ; - k = (k+N_COL) & 15 ; - byte d = st [l] ; - l = (l+N_COL) & 15 ; - byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ; - byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; - dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ; - dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ; - dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ; - dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ; - } -} - -static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK]) -{ - for (byte i = 0 ; i < N_BLOCK ; i += N_COL) { - byte a1 = st [i] ; - byte b1 = st [i+1] ; - byte c1 = st [i+2] ; - byte d1 = st [i+3] ; - byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; - byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ; - byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ; - byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ; - byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ; - - dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ; - dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ; - dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ; - dt[(i+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ; - } -} - -/******************************************************************************/ - -AES::AES() -{ - byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; - IVC = 0x01; - round = 0; - pad = 0; - size = 0; - memset(key_sched, 0, KEY_SCHEDULE_BYTES); - memcpy(iv,ar_iv,8); - memcpy(iv+8,ar_iv,8); - arr_pad[0] = 0x01; - arr_pad[1] = 0x02; - arr_pad[2] = 0x03; - arr_pad[3] = 0x04; - arr_pad[4] = 0x05; - arr_pad[5] = 0x06; - arr_pad[6] = 0x07; - arr_pad[7] = 0x08; - arr_pad[8] = 0x09; - arr_pad[9] = 0x0a; - arr_pad[10] = 0x0b; - arr_pad[11] = 0x0c; - arr_pad[12] = 0x0d; - arr_pad[13] = 0x0e; - arr_pad[14] = 0x0f; -} - -/******************************************************************************/ - -byte AES::set_key (byte key [], int keylen) -{ - byte hi ; - switch (keylen) { - case 16: - case 128: - keylen = 16; // 10 rounds - round = 10 ; - break; - case 24: - case 192: - keylen = 24; // 12 rounds - round = 12 ; - break; - case 32: - case 256: - keylen = 32; // 14 rounds - round = 14 ; - break; - default: - round = 0; - return AES_FAILURE; - } - hi = (round + 1) << 4 ; - copy_n_bytes (key_sched, key, keylen) ; - byte t[4] ; - byte next = keylen ; - for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) { - for (byte i = 0 ; i < N_COL ; i++) { - t[i] = key_sched [cc-4+i] ; - } - if (cc == next) { - next += keylen ; - byte ttt = t[0] ; - t[0] = s_box (t[1]) ^ rc ; - t[1] = s_box (t[2]) ; - t[2] = s_box (t[3]) ; - t[3] = s_box (ttt) ; - rc = f2 (rc) ; - } else if (keylen == 32 && (cc & 31) == 16) { - for (byte i = 0 ; i < 4 ; i++) { - t[i] = s_box (t[i]) ; - } - } - byte tt = cc - keylen ; - for (byte i = 0 ; i < N_COL ; i++) { - key_sched [cc + i] = key_sched [tt + i] ^ t[i] ; - } - } - return AES_SUCCESS ; -} - -/******************************************************************************/ - -void AES::clean () -{ - for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++) { - key_sched [i] = 0 ; - } - round = 0 ; -} - -/******************************************************************************/ - -void AES::copy_n_bytes (byte * d, byte * s, byte nn) -{ - while (nn >= 4) { - *d++ = *s++ ; // some unrolling - *d++ = *s++ ; - *d++ = *s++ ; - *d++ = *s++ ; - nn -= 4 ; - } - while (nn--) { - *d++ = *s++ ; - } -} - -/******************************************************************************/ - -byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) -{ - if (round) { - byte s1 [N_BLOCK], r ; - copy_and_key (s1, plain, (byte*) (key_sched)) ; - - for (r = 1 ; r < round ; r++) { - byte s2 [N_BLOCK] ; - mix_sub_columns (s2, s1) ; - copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ; - } - shift_sub_rows (s1) ; - copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ; - } else { - return AES_FAILURE ; - } - return AES_SUCCESS ; -} - -/******************************************************************************/ - -byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) -{ - while (n_block--) { - xor_block (iv, plain) ; - if (encrypt (iv, iv) != AES_SUCCESS) { - return AES_FAILURE ; - } - copy_n_bytes (cipher, iv, N_BLOCK) ; - plain += N_BLOCK ; - cipher += N_BLOCK ; - } - return AES_SUCCESS ; -} - -/******************************************************************************/ - -byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block) -{ - while (n_block--) { - xor_block (iv, plain) ; - if (encrypt (iv, iv) != AES_SUCCESS) { - return AES_FAILURE ; - } - copy_n_bytes (cipher, iv, N_BLOCK) ; - plain += N_BLOCK ; - cipher += N_BLOCK ; - } - return AES_SUCCESS ; -} - -/******************************************************************************/ - -byte AES::decrypt (byte cipher [N_BLOCK], byte plain [N_BLOCK]) -{ - if (round) { - byte s1 [N_BLOCK] ; - copy_and_key (s1, cipher, (byte*) (key_sched + round * N_BLOCK)) ; - inv_shift_sub_rows (s1) ; - - for (byte r = round ; --r ; ) { - byte s2 [N_BLOCK] ; - copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ; - inv_mix_sub_columns (s1, s2) ; - } - copy_and_key (plain, s1, (byte*) (key_sched)) ; - } else { - return AES_FAILURE ; - } - return AES_SUCCESS ; -} - -/******************************************************************************/ - -byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) -{ - while (n_block--) { - byte tmp [N_BLOCK] ; - copy_n_bytes (tmp, cipher, N_BLOCK) ; - if (decrypt (cipher, plain) != AES_SUCCESS) { - return AES_FAILURE ; - } - xor_block (plain, iv) ; - copy_n_bytes (iv, tmp, N_BLOCK) ; - plain += N_BLOCK ; - cipher += N_BLOCK; - } - return AES_SUCCESS ; -} - -/******************************************************************************/ - -byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block) -{ - while (n_block--) { - byte tmp [N_BLOCK] ; - copy_n_bytes (tmp, cipher, N_BLOCK) ; - if (decrypt (cipher, plain) != AES_SUCCESS) { - return AES_FAILURE ; - } - xor_block (plain, iv) ; - copy_n_bytes (iv, tmp, N_BLOCK) ; - plain += N_BLOCK ; - cipher += N_BLOCK; - } - return AES_SUCCESS ; -} - -/*****************************************************************************/ - -void AES::set_IV(unsigned long long int IVCl) -{ - memcpy(iv,&IVCl,8); - memcpy(iv+8,&IVCl,8); - IVC = IVCl; -} - -/******************************************************************************/ - -void AES::iv_inc() -{ - IVC += 1; - memcpy(iv,&IVC,8); - memcpy(iv+8,&IVC,8); -} - -/******************************************************************************/ - -int AES::get_size() -{ - return size; -} - -/******************************************************************************/ - -void AES::set_size(int sizel) -{ - size = sizel; -} - - -/******************************************************************************/ - -void AES::get_IV(byte *out) -{ - memcpy(out,&IVC,8); - memcpy(out+8,&IVC,8); -} - -/******************************************************************************/ - -void AES::calc_size_n_pad(int p_size) -{ - int s_of_p = p_size - 1; - if ( s_of_p % N_BLOCK == 0) { - size = s_of_p; - } else { - size = s_of_p + (N_BLOCK-(s_of_p % N_BLOCK)); - } - pad = size - s_of_p; -} - -/******************************************************************************/ - -void AES::padPlaintext(void* in,byte* out) -{ - memcpy(out,in,size); - for (int i = size-pad; i < size; i++) { - ; - out[i] = arr_pad[pad - 1]; - } -} - -/******************************************************************************/ - -bool AES::CheckPad(byte* in,int lsize) -{ - if (in[lsize-1] <= 0x0f) { - int lpad = (int)in[lsize-1]; - for (int i = lsize - 1; i >= lsize-lpad; i--) { - if (arr_pad[lpad - 1] != in[i]) { - return false; - } - } - } else { - return true; - } - return true; -} - -/******************************************************************************/ - -void AES::printArray(byte output[],bool p_pad) -{ - uint8_t i,j; - uint8_t loops = size/N_BLOCK; - uint8_t outp = N_BLOCK; - for (j = 0; j < loops; j += 1) { - if (p_pad && (j == (loops - 1)) ) { - outp = N_BLOCK - pad; - } - for (i = 0; i < outp; i++) { - printf_P(PSTR("%c"),output[j*N_BLOCK + i]); - } - } - printf_P(PSTR("\n")); -} - -/******************************************************************************/ - -void AES::printArray(byte output[],int sizel) -{ - for (int i = 0; i < sizel; i++) { - printf_P(PSTR("%x"),output[i]); - } - printf_P(PSTR("\n")); -} - - -/******************************************************************************/ - -void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, - byte ivl [N_BLOCK]) -{ - calc_size_n_pad(size_p); - byte plain_p[get_size()]; - padPlaintext(plain,plain_p); - int blocks = get_size() / N_BLOCK; - set_key (key, bits) ; - cbc_encrypt (plain_p, cipher, blocks, ivl); -} - -/******************************************************************************/ - -void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits) -{ - calc_size_n_pad(size_p); - byte plain_p[get_size()]; - padPlaintext(plain,plain_p); - int blocks = get_size() / N_BLOCK; - set_key (key, bits) ; - cbc_encrypt (plain_p, cipher, blocks); -} - -/******************************************************************************/ - -void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, - byte ivl [N_BLOCK]) -{ - set_size(size_c); - int blocks = size_c / N_BLOCK; - set_key (key, bits); - cbc_decrypt (cipher,plain, blocks, ivl); -} - -/******************************************************************************/ - -void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits) -{ - set_size(size_c); - int blocks = size_c / N_BLOCK; - set_key (key, bits); - cbc_decrypt (cipher,plain, blocks); -} - - -/******************************************************************************/ - -#if defined(AES_LINUX) -double AES::millis() -{ - gettimeofday(&tv, NULL); - return (tv.tv_sec + 0.000001 * tv.tv_usec); -} -#endif diff --git a/lib/MySensors/hal/crypto/generic/drivers/AES/AES.h b/lib/MySensors/hal/crypto/generic/drivers/AES/AES.h deleted file mode 100644 index 3c49f4e0..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/AES/AES.h +++ /dev/null @@ -1,381 +0,0 @@ -#ifndef __AES_H__ -#define __AES_H__ - -#include "AES_config.h" -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The redistribution and use of this software (with or without changes) - is allowed without the payment of fees or royalties provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue 09/09/2006 - - This is an AES implementation that uses only 8-bit byte operations on the - cipher state. - */ - -/* code was modified by george spanos -* 16/12/14 -*/ -/** AES class */ -class AES -{ -public: - - /* The following calls are for a precomputed key schedule - - NOTE: If the length_type used for the key length is an - unsigned 8-bit character, a key length of 256 bits must - be entered as a length in bytes (valid inputs are hence - 128, 192, 16, 24 and 32). - */ - /** \fn AES() - * \brief AES constructor - * - * This function initialized an instance of AES. - */ - AES(); - - /** Set the cipher key for the pre-keyed version. - * @param key[] pointer to the key string. - * @param keylen Integer that indicates the length of the key. - * @note NOTE: If the length_type used for the key length is an unsigned 8-bit character, - * a key length of 256 bits must be entered as a length in bytes - * (valid inputs are hence 128, 192, 16, 24 and 32). - * - */ - byte set_key (byte key[], int keylen) ; - - /** clean up subkeys after use. - * - */ - void clean () ; // delete key schedule after use - - /** copying and xoring utilities. - * @param *AESt byte pointer of the AEStination array. - * @param *src byte pointer of the source array. - * @param n byte, indicating the sizeof the bytes to be copied. - * @note this is an alternative for memcpy(void *s1,const void *s2, site_t n), - * i have not updated the function in the implementation yet, but it is considered a future plan. - * - */ - void copy_n_bytes (byte * AESt, byte * src, byte n) ; - - /** Encrypt a single block of 16 bytes . - * @param plain Array of the plaintext. - * @param cipher Array of the ciphertext. - * @note The N_BLOCK is defined in AES_config.h as, - * @code #define N_ROW 4 - * #define N_COL 4 - * #define N_BLOCK (N_ROW * N_COL) - * @endcode - * Changed to that will change the Block_size. - * @return 0 if SUCCESS or -1 if FAILURE - * - */ - byte encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) ; - - /** CBC encrypt a number of blocks (input and return an IV). - * - * @param *plain Pointer, points to the plaintex. - * @param *cipher Pointer, points to the ciphertext that will be created. - * @param n_block integer, indicated the number of blocks to be ciphered. - * @param iv byte Array that holds the IV (initialization vector). - * @return 0 if SUCCESS or -1 if FAILURE - * - */ - byte cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) ; - - /** CBC encrypt a number of blocks (input and return an IV). - * - * @param *plain Pointer, points to the plaintex. - * @param *cipher Pointer, points to the ciphertext that will be created. - * @param n_block integer, indicated the number of blocks to be ciphered. - * @return 0 if SUCCESS or -1 if FAILURE - * - */ - byte cbc_encrypt (byte * plain, byte * cipher, int n_block) ; - - - /** Decrypt a single block of 16 bytes - * @param cipher Array of the ciphertext. - * @param plain Array of the plaintext. - * @note The N_BLOCK is defined in AES_config.h as, - * @code #define N_ROW 4 - * #define N_COL 4 - * #define N_BLOCK (N_ROW * N_COL) - * @endcode - * Changed to that will change the Block_size. - * @return 0 if SUCCESS or -1 if FAILURE - * - */ - byte decrypt (byte cipher [N_BLOCK], byte plain [N_BLOCK]) ; - - /** CBC decrypt a number of blocks (input and return an IV) - * - * @param *cipher Pointer, points to the ciphertext that will be created. - * @param *plain Pointer, points to the plaintex. - * @param n_block integer, indicated the number of blocks to be ciphered. - * @param iv byte Array that holds the IV (initialization vector). - * @return 0 if SUCCESS or -1 if FAILURE - * - */ - byte cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) ; - - /** CBC decrypt a number of blocks (input and return an IV) - * - * @param *cipher Pointer, points to the ciphertext that will be created. - * @param *plain Pointer, points to the plaintex. - * @param n_block integer, indicated the number of blocks to be ciphered. - * @return 0 if SUCCESS or -1 if FAILURE - * - */ - byte cbc_decrypt (byte * cipher, byte * plain, int n_block) ; - - /** Sets IV (initialization vector) and IVC (IV counter). - * This function changes the ivc and iv variables needed for AES. - * - * @param IVCl int or hex value of iv , ex. 0x0000000000000001 - * @note example: - * @code unsigned long long int my_iv = 01234567; @endcode - */ - void set_IV(unsigned long long int IVCl); - - /** increase the iv (initialization vector) and IVC (IV counter) by 1 - * - * This function increased the VI by one step in order to have a different IV each time - * - */ - void iv_inc(); - - /** Getter method for size - * - * This function return the size - * @return an integer, that is the size of the of the padded plaintext, - * thus, the size of the ciphertext. - */ - int get_size(); - - /** Setter method for size - * - * This function sets the size of the plaintext+pad - * - */ - void set_size(int sizel); - - /** Getter method for IV - * - * This function return the IV - * @param out byte pointer that gets the IV. - * @return none, the IV is writed to the out pointer. - */ - void get_IV(byte *out); - - /** Calculates the size of the plaintext and the padding. - * - * Calculates the size of theplaintext with the padding - * and the size of the padding needed. Moreover it stores them in their class variables. - * - * @param p_size the size of the byte array ex sizeof(plaintext) - */ - void calc_size_n_pad(int p_size); - - /** Pads the plaintext - * - * This function pads the plaintext and returns an char array with the - * plaintext and the padding in order for the plaintext to be compatible with - * 16bit size blocks required by AES - * - * @param in the string of the plaintext in a byte array - * @param out The string of the out array. - * @return no return, The padded plaintext is stored in the out pointer. - */ - void padPlaintext(void* in,byte* out); - - /** Check the if the padding is correct. - * - * This functions checks the padding of the plaintext. - * - * @param in the string of the plaintext in a byte array - * @param size the size of the string - * @return true if correct / false if not - */ - bool CheckPad(byte* in,int size); - - /** Prints the array given. - * - * This function prints the given array and pad, - * It is mainlly used for debugging purpuses or to output the string. - * - * @param output[] the string of the text in a byte array - * @param p_pad optional, used to print with out the padding characters - */ - void printArray(byte output[],bool p_pad = true); - - /** Prints the array given. - * - * This function prints the given array in Hexadecimal. - * - * @param output[] the string of the text in a byte array - * @param sizel the size of the array. - */ - void printArray(byte output[],int sizel); - - /** User friendly implementation of AES-CBC encryption. - * - * @param *plain pointer to the plaintext - * @param size_p size of the plaintext - * @param *cipher pointer to the ciphertext - * @param *key pointer to the key that will be used. - * @param bits bits of the encryption/decrpytion - * @param ivl the initialization vector IV that will be used for encryption. - * @note The key will be stored in class variable. - */ - void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]); - - /** User friendly implementation of AES-CBC encryption. - * - * @param *plain pointer to the plaintext - * @param size_p size of the plaintext - * @param *cipher pointer to the ciphertext - * @param *key pointer to the key that will be used. - * @param bits bits of the encryption/decrpytion - * @note The key will be stored in class variable. - */ - void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits); - - /** User friendly implementation of AES-CBC decryption. - * - * @param *cipher pointer to the ciphertext - * @param size_c size of the ciphertext - * @param *plain pointer to the plaintext - * @param *key pointer to the key that will be used. - * @param bits bits of the encryption/decrpytion - * @param ivl the initialization vector IV that will be used for decryption. - * @note The key will be stored in class variable. - */ - void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]); - - /** User friendly implementation of AES-CBC decryption. - * - * @param *cipher pointer to the ciphertext - * @param size_c size of the ciphertext - * @param *plain pointer to the plaintext - * @param *key pointer to the key that will be used. - * @param bits bits of the encryption/decrpytion - * @note The key will be stored in class variable. - */ - void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits); - -#if defined(AES_LINUX) - /** - * used in linux in order to retrieve the time in milliseconds. - * - * @return returns the milliseconds in a double format. - */ - double millis(); -#endif -private: - int round ;/**< holds the number of rounds to be used. */ - byte key_sched [KEY_SCHEDULE_BYTES] - ;/**< holds the pre-computed key for the encryption/decrpytion. */ - unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */ - byte iv[16];/**< holds the initialization vector that will be used in the cipher. */ - int pad;/**< holds the size of the padding. */ - int size;/**< hold the size of the plaintext to be ciphered */ -#if defined(AES_LINUX) - timeval tv;/**< holds the time value on linux */ - byte arr_pad[15];/**< holds the hexadecimal padding values on linux */ -#else - byte arr_pad[15];// = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };/**< holds the hexadecimal padding values */ -#endif -} ; - - -#endif - -/** - * @defgroup aeslib AES library for Arduino and Raspberry pi - * @ingroup internals - * - * @section AesGoals design Goals - * - * This library is AESigned to be... - * @li Fast and efficient. - * @li Able to effectively encrypt and decrypt any size of string. - * @li Able to encrypt and decrypt using AES - * @li Able to encrypt and decrypt using AES-CBC - * @li Easy for the user to use in his programs. - * - * @section Acknowledgements Acknowledgements - * This is an AES library for the Arduino, based on tzikis's AES library, which you can find here:.
- * Tzikis library was based on scottmac`s library, which you can find here:
- * - * @section Installation Installation - *

Arduino

- * Create a folder named _AES_ in the _libraries_ folder inside your Arduino sketch folder. If the - * libraries folder doesn't exist, create it. Then copy everything inside. (re)launch the Arduino IDE.
- * You're done. Time for a mojito - * - *

Raspberry pi

- * install

- * - * sudo make install
- * cd examples_Rpi
- * make

- * - * What to do after changes to the library

- * sudo make clean
- * sudo make install
- * cd examples_Rpi
- * make clean
- * make

- * What to do after changes to a sketch

- * cd examples_Rpi
- * make \

- * or
- * make clean
- * make


- * How to start a sketch

- * cd examples_Rpi
- * sudo ./\

- * - * @section AesNews News - * - * If issues are discovered with the documentation, please report them here - * @section AesUseful Useful References - * - * Please refer to: - * - * @li AES Class Documentation - * @li Download - * @li Source Code - * @li All spaniakos Documentation Main Page - * - * @section AesBoard_Support Board Support - * - * Most standard Arduino based boards are supported: - * - Arduino - * - Intel Galileo support - * - Raspberry Pi Support - * - * - The library has not been tested to other boards, but it should suppport ATMega 328 based boards,Mega Boards,Arduino Due,ATTiny board - */ diff --git a/lib/MySensors/hal/crypto/generic/drivers/AES/AES_config.h b/lib/MySensors/hal/crypto/generic/drivers/AES/AES_config.h deleted file mode 100644 index aa608a1a..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/AES/AES_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* code was modified by george spanos - * 16/12/14 - */ - -#ifndef __AES_CONFIG_H__ -#define __AES_CONFIG_H__ - -#if (defined(__linux) || defined(linux)) && !defined(__ARDUINO_X86__) - -#define AES_LINUX - -#include -#include -#include -#include -#include -#include -#else -#include -#endif - -#include -#include - -#if defined(__ARDUINO_X86__) || (defined (__linux) || defined (linux)) -#undef PROGMEM -#define PROGMEM __attribute__(( section(".progmem.data") )) -#define pgm_read_byte(p) (*(p)) -typedef unsigned char byte; -#define printf_P printf -#define PSTR(x) (x) -#elif defined(ARDUINO_ARCH_ESP8266) -#include -#elif defined(ARDUINO_ARCH_ESP32) -#include -#elif defined(ARDUINO_ARCH_SAMD) -#define printf_P printf -#else -#include -#endif - -#define N_ROW 4 -#define N_COL 4 -#define N_BLOCK (N_ROW * N_COL) -#define N_MAX_ROUNDS 14 -#define KEY_SCHEDULE_BYTES ((N_MAX_ROUNDS + 1) * N_BLOCK) -#define AES_SUCCESS (0) -#define AES_FAILURE (-1) - -#endif diff --git a/lib/MySensors/hal/crypto/generic/drivers/AES/README.MD b/lib/MySensors/hal/crypto/generic/drivers/AES/README.MD deleted file mode 100644 index 2337a4eb..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/AES/README.MD +++ /dev/null @@ -1,91 +0,0 @@ -### Arduino -just run the sketched aftel loading the libraries. - -### Raspberry pi -install -``` -sudo make install -cd examples_Rpi -make -``` - -What to do after changes to the library -``` -sudo make clean -sudo make install -cd examples_Rpi -make clean -make -``` - -What to do after changes to a sketch -``` -cd examples_Rpi -make - -or -make clean -make -``` - -How to start a sketch -``` -cd examples_Rpi -sudo ./ -``` - -This is a derived work from Brian Gladman's AES implementation for byte-oriented -processors, here's the licence terms: - -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The redistribution and use of this software (with or without changes) - is allowed without the payment of fees or royalties provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue 09/09/2006 - - This is an AES implementation that uses only 8-bit byte operations on the - cipher state (there are options to use 32-bit types if available). - - The combination of mix columns and byte substitution used here is based on - that developed by Karl Malbrain. His contribution is acknowledged. - */ - -/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down - and tailored to 8-bit microcontroller abilities and Arduino datatypes. - - The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all - the other transformations are coded to save table space. Many efficiency - improvments to the routines mix_sub_columns() and inv_mix_sub_columns() - (mainly common sub-expression elimination). - - Only the routines with precalculated subkey schedule are retained (together - with set_key() - this does however mean each AES object takes 240 bytes of - RAM, alas) - - The CBC routines side-effect the iv argument (so that successive calls work - together correctly). - - All the encryption and decryption routines work with plain == cipher for - in-place encryption, note. - -*/ diff --git a/lib/MySensors/hal/crypto/generic/drivers/AES/keywords.txt b/lib/MySensors/hal/crypto/generic/drivers/AES/keywords.txt deleted file mode 100644 index 8dbba38d..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/AES/keywords.txt +++ /dev/null @@ -1,7 +0,0 @@ -AES KEYWORD1 -set_key KEYWORD2 -clean KEYWORD2 -encrypt KEYWORD2 -decrypt KEYWORD2 -cbc_encrypt KEYWORD2 -cbc_decrypt KEYWORD2 diff --git a/lib/MySensors/hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.cpp b/lib/MySensors/hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.cpp deleted file mode 100644 index f581a878..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -*/ - -#include "hmac_sha256.h" - -void SHA256HMACInit(const uint8_t *key, size_t keyLength) -{ - (void)memset((void *)&SHA256keyBuffer, 0x00, BLOCK_LENGTH); - if (keyLength > BLOCK_LENGTH) { - // Hash long keys - SHA256Init(); - SHA256Add(key, keyLength); - SHA256Result(SHA256keyBuffer); - } else { - // Block length keys are used as is - (void)memcpy((void *)SHA256keyBuffer, (const void *)key, keyLength); - } - // Start inner hash - SHA256Init(); - for (uint8_t i = 0; i < BLOCK_LENGTH; i++) { - SHA256Add(SHA256keyBuffer[i] ^ HMAC_IPAD); - } -} - -void SHA256HMACAdd(const uint8_t data) -{ - SHA256Add(data); -} - -void SHA256HMACAdd(const uint8_t *data, size_t dataLength) -{ - SHA256Add(data, dataLength); -} - -void SHA256HMACResult(uint8_t *dest) -{ - uint8_t innerHash[HASH_LENGTH]; - // Complete inner hash - SHA256Result(innerHash); - // Calculate outer hash - SHA256Init(); - for (uint8_t i = 0; i < BLOCK_LENGTH; i++) { - SHA256Add(SHA256keyBuffer[i] ^ HMAC_OPAD); - } - SHA256Add(innerHash, HASH_LENGTH); - SHA256Result(dest); -} \ No newline at end of file diff --git a/lib/MySensors/hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.h b/lib/MySensors/hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.h deleted file mode 100644 index 38dd256e..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/HMAC_SHA256/hmac_sha256.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -*/ - -#ifndef _HMAC_SHA256_ -#define _HMAC_SHA256_ - -#define HMAC_IPAD 0x36 //!< HMAC_IPAD -#define HMAC_OPAD 0x5c //!< HMAC_OPAD - - -#endif diff --git a/lib/MySensors/hal/crypto/generic/drivers/SHA256/sha256.cpp b/lib/MySensors/hal/crypto/generic/drivers/SHA256/sha256.cpp deleted file mode 100644 index b14f77a9..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/SHA256/sha256.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -*/ - -#include "sha256.h" - -const uint32_t SHA256K[] PROGMEM = { - 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, - 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, - 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, - 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, - 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, - 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, - 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, - 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 -}; - -const uint8_t SHA256InitState[] PROGMEM = { - 0x67,0xe6,0x09,0x6a, // H0 - 0x85,0xae,0x67,0xbb, // H1 - 0x72,0xf3,0x6e,0x3c, // H2 - 0x3a,0xf5,0x4f,0xa5, // H3 - 0x7f,0x52,0x0e,0x51, // H4 - 0x8c,0x68,0x05,0x9b, // H5 - 0xab,0xd9,0x83,0x1f, // H6 - 0x19,0xcd,0xe0,0x5b // H7 -}; - -_SHA256buffer_t SHA256buffer; -uint8_t SHA256bufferOffset; -_SHA256state_t SHA256state; -uint32_t SHA256byteCount; -uint8_t SHA256keyBuffer[BLOCK_LENGTH]; - -void SHA256Init(void) -{ - (void)memcpy_P((void *)&SHA256state.b, (const void *)&SHA256InitState, 32); - SHA256byteCount = 0; - SHA256bufferOffset = 0; -} - -uint32_t SHA256ror32(const uint32_t number, const uint8_t bits) -{ - return ((number << (32 - bits)) | (number >> bits)); -} - -void SHA256hashBlock(void) -{ - uint32_t a, b, c, d, e, f, g, h, t1, t2; - - a = SHA256state.w[0]; - b = SHA256state.w[1]; - c = SHA256state.w[2]; - d = SHA256state.w[3]; - e = SHA256state.w[4]; - f = SHA256state.w[5]; - g = SHA256state.w[6]; - h = SHA256state.w[7]; - - for (uint8_t i = 0; i < 64; i++) { - if (i >= 16) { - t1 = SHA256buffer.w[i & 15] + SHA256buffer.w[(i - 7) & 15]; - t2 = SHA256buffer.w[(i - 2) & 15]; - t1 += SHA256ror32(t2, 17) ^ SHA256ror32(t2, 19) ^ (t2 >> 10); - t2 = SHA256buffer.w[(i - 15) & 15]; - t1 += SHA256ror32(t2, 7) ^ SHA256ror32(t2, 18) ^ (t2 >> 3); - SHA256buffer.w[i & 15] = t1; - } - t1 = h; - t1 += SHA256ror32(e, 6) ^ SHA256ror32(e, 11) ^ SHA256ror32(e, 25); // ∑1(e) - t1 += g ^ (e & (g ^ f)); // Ch(e,f,g) - t1 += pgm_read_dword(SHA256K + i); // Ki - t1 += SHA256buffer.w[i & 15]; // Wi - t2 = SHA256ror32(a, 2) ^ SHA256ror32(a, 13) ^ SHA256ror32(a, 22); // ∑0(a) - t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c) - h = g; - g = f; - f = e; - e = d + t1; - d = c; - c = b; - b = a; - a = t1 + t2; - } - SHA256state.w[0] += a; - SHA256state.w[1] += b; - SHA256state.w[2] += c; - SHA256state.w[3] += d; - SHA256state.w[4] += e; - SHA256state.w[5] += f; - SHA256state.w[6] += g; - SHA256state.w[7] += h; -} - -void SHA256addUncounted(const uint8_t data) -{ - SHA256buffer.b[SHA256bufferOffset ^ 3] = data; - SHA256bufferOffset++; - if (SHA256bufferOffset == BLOCK_LENGTH) { - SHA256hashBlock(); - SHA256bufferOffset = 0; - } -} - - -void SHA256Add(const uint8_t data) -{ - SHA256byteCount++; - SHA256addUncounted(data); -} - -void SHA256Add(const uint8_t *data, size_t dataLength) -{ - while (dataLength--) { - SHA256Add(*data++); - } -} - -void SHA256Result(uint8_t *dest) -{ - // Pad to complete the last block - SHA256addUncounted(0x80); - while (SHA256bufferOffset != 56) { - SHA256addUncounted(0x00); - } - - // Append length in the last 8 bytes - SHA256addUncounted(0); // We're only using 32 bit lengths - SHA256addUncounted(0); // But SHA-1 supports 64 bit lengths - SHA256addUncounted(0); // So zero pad the top bits - SHA256addUncounted(SHA256byteCount >> 29); // Shifting to multiply by 8 - SHA256addUncounted(SHA256byteCount >> 21); // as SHA-1 supports bitstreams as well as - SHA256addUncounted(SHA256byteCount >> 13); // byte. - SHA256addUncounted(SHA256byteCount >> 5); - SHA256addUncounted(SHA256byteCount << 3); - - // Swap byte order back - for (uint8_t i = 0; i<8; i++) { - uint32_t a, b; - a = SHA256state.w[i]; - b = a << 24; - b |= (a << 8) & 0x00ff0000; - b |= (a >> 8) & 0x0000ff00; - b |= a >> 24; - SHA256state.w[i] = b; - } - (void)memcpy((void *)dest, (const void *)SHA256state.b, 32); - // Return pointer to hash (20 characters) - //return SHA256state.b; -} - -void SHA256(uint8_t *dest, const uint8_t *data, size_t dataLength) -{ - SHA256Init(); - SHA256Add(data, dataLength); - SHA256Result(dest); -} diff --git a/lib/MySensors/hal/crypto/generic/drivers/SHA256/sha256.h b/lib/MySensors/hal/crypto/generic/drivers/SHA256/sha256.h deleted file mode 100644 index 4081a8e1..00000000 --- a/lib/MySensors/hal/crypto/generic/drivers/SHA256/sha256.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -*/ - -#ifndef _SHA256_H_ -#define _SHA256_H_ - -#define HASH_LENGTH 32 //!< HASH_LENGTH -#define BLOCK_LENGTH 64 //!< BLOCK_LENGTH - -/** -* @brief buffer for SHA256 calculator -*/ -union _SHA256buffer_t { - uint8_t b[BLOCK_LENGTH]; //!< SHA256 b - uint32_t w[BLOCK_LENGTH / 4]; //!< SHA256 w -}; - -/** -* @brief state variables for SHA256 calculator -*/ -union _SHA256state_t { - uint8_t b[HASH_LENGTH]; //!< SHA256 b - uint32_t w[HASH_LENGTH / 4]; //!< SHA256 w -}; - -#endif diff --git a/lib/MySensors/hal/transport/MyTransportHAL.cpp b/lib/MySensors/hal/transport/MyTransportHAL.cpp deleted file mode 100644 index 9bf35c45..00000000 --- a/lib/MySensors/hal/transport/MyTransportHAL.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - */ - -#include "MyTransportHAL.h" - -#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL) -#define TRANSPORT_HAL_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< debug -#else -#define TRANSPORT_HAL_DEBUG(x,...) //!< debug NULL -#endif - -bool transportHALInit(void) -{ - TRANSPORT_HAL_DEBUG(PSTR("THA:INIT\n")); -#if defined(MY_TRANSPORT_ENCRYPTION) - uint8_t transportPSK[16]; -#if defined(MY_ENCRYPTION_SIMPLE_PASSWD) - (void)memset((void *)transportPSK, 0, sizeof(transportPSK)); - (void)memcpy((void *)transportPSK, MY_ENCRYPTION_SIMPLE_PASSWD, - strnlen(MY_ENCRYPTION_SIMPLE_PASSWD, sizeof(transportPSK))); -#else - hwReadConfigBlock((void *)transportPSK, (void *)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, - sizeof(transportPSK)); -#endif -#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL) - hwDebugBuf2Str((const uint8_t *)transportPSK, sizeof(transportPSK)); - TRANSPORT_HAL_DEBUG(PSTR("THA:INIT:PSK=%s\n"),hwDebugPrintStr); -#endif -#endif - bool result = transportInit(); - -#if defined(MY_TRANSPORT_ENCRYPTION) -#if defined(MY_RADIO_RFM69) - transportEncrypt((const char *)transportPSK); -#else - //set up AES-key - AES128CBCInit(transportPSK); -#endif - // Make sure it is purged from memory when set - (void)memset((void *)transportPSK, 0, - sizeof(transportPSK)); -#endif - return result; -} - -void transportHALSetAddress(const uint8_t address) -{ - TRANSPORT_HAL_DEBUG(PSTR("THA:SAD:ADDR=%" PRIu8 "\n"), address); - transportSetAddress(address); -} - -uint8_t transportHALGetAddress(void) -{ - uint8_t result = transportGetAddress(); - TRANSPORT_HAL_DEBUG(PSTR("THA:GAD:ADDR=%" PRIu8 "\n"), result); - return result; -} - -bool transportHALDataAvailable(void) -{ - bool result = transportDataAvailable(); -#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL) - if (result) { - TRANSPORT_HAL_DEBUG(PSTR("THA:DATA:AVAIL\n")); - } -#endif - return result; -} - -bool transportHALSanityCheck(void) -{ - bool result = transportSanityCheck(); - TRANSPORT_HAL_DEBUG(PSTR("THA:SAN:RES=%" PRIu8 "\n"), result); - return result; -} - -bool transportHALReceive(MyMessage *inMsg, uint8_t *msgLength) -{ - // set pointer to first byte of data structure - uint8_t *rx_data = &inMsg->last; - uint8_t payloadLength = transportReceive((void *)rx_data); -#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL) - hwDebugBuf2Str((const uint8_t *)rx_data, payloadLength); - TRANSPORT_HAL_DEBUG(PSTR("THA:RCV:MSG=%s\n"), hwDebugPrintStr); -#endif -#if defined(MY_TRANSPORT_ENCRYPTION) && !defined(MY_RADIO_RFM69) - TRANSPORT_HAL_DEBUG(PSTR("THA:RCV:DECRYPT\n")); - // has to be adjusted, WIP! - uint8_t IV[16] = { 0 }; - // decrypt data - AES128CBCDecrypt(IV, (uint8_t *)rx_data, payloadLength); -#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL) - hwDebugBuf2Str((const uint8_t *)rx_data, payloadLength); - TRANSPORT_HAL_DEBUG(PSTR("THA:RCV:PLAIN=%s\n"), hwDebugPrintStr); -#endif -#endif - // Reject messages with incorrect protocol version - MyMessage tmp = *inMsg; - if (!tmp.isProtocolVersionValid()) { - setIndication(INDICATION_ERR_VERSION); - TRANSPORT_HAL_DEBUG(PSTR("!THA:RCV:PVER=%" PRIu8 "\n"), - tmp.getVersion()); // protocol version mismatch - return false; - } - *msgLength = tmp.getLength(); -#if defined(MY_TRANSPORT_ENCRYPTION) && !defined(MY_RADIO_RFM69) - // payload length = a multiple of blocksize length for decrypted messages, i.e. cannot be used for payload length check -#else - // Reject payloads with incorrect length - const uint8_t expectedMessageLength = tmp.getExpectedMessageSize(); - if (payloadLength != expectedMessageLength) { - setIndication(INDICATION_ERR_LENGTH); - TRANSPORT_HAL_DEBUG(PSTR("!THA:RCV:LEN=%" PRIu8 ",EXP=%" PRIu8 "\n"), payloadLength, - expectedMessageLength); // invalid payload length - return false; - } -#endif - TRANSPORT_HAL_DEBUG(PSTR("THA:RCV:MSG LEN=%" PRIu8 "\n"), payloadLength); - return true; -} - -bool transportHALSend(const uint8_t nextRecipient, const MyMessage *outMsg, const uint8_t len, - const bool noACK) -{ - if (outMsg == NULL) { - - // nothing to send - return false; - } -#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL) - hwDebugBuf2Str((const uint8_t *)&outMsg->last, len); - TRANSPORT_HAL_DEBUG(PSTR("THA:SND:MSG=%s\n"), hwDebugPrintStr); -#endif - -#if defined(MY_TRANSPORT_ENCRYPTION) && !defined(MY_RADIO_RFM69) - TRANSPORT_HAL_DEBUG(PSTR("THA:SND:ENCRYPT\n")); - uint8_t *tx_data[MAX_MESSAGE_SIZE]; - // copy input data because it is read-only - (void)memcpy((void *)tx_data, (void *)&outMsg->last, len); - // We us IV vector filled with zeros but randomize unused bytes in encryption block - uint8_t IV[16] = { 0 }; - const uint8_t finalLength = len > 16 ? 32 : 16; - // fill block with random data - for (uint8_t i = len; i < finalLength; i++) { - *((uint8_t *)tx_data + i) = random(256); - } - //encrypt data - AES128CBCEncrypt(IV, (uint8_t *)tx_data, finalLength); -#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL) - hwDebugBuf2Str((const uint8_t *)tx_data, finalLength); - TRANSPORT_HAL_DEBUG(PSTR("THA:SND:CIP=%s\n"), hwDebugPrintStr); -#endif - -#else - const uint8_t *tx_data = &outMsg->last; - const uint8_t finalLength = len; -#endif - - bool result = transportSend(nextRecipient, (void *)tx_data, finalLength, noACK); - TRANSPORT_HAL_DEBUG(PSTR("THA:SND:MSG LEN=%" PRIu8 ",RES=%" PRIu8 "\n"), finalLength, result); - return result; -} - -void transportHALPowerDown(void) -{ - transportPowerDown(); -} - -void transportHALPowerUp(void) -{ - transportPowerUp(); -} - -void transportHALSleep(void) -{ - transportSleep(); -} - -void transportHALStandBy(void) -{ - transportStandBy(); -} - -int16_t transportHALGetSendingRSSI(void) -{ - int16_t result = transportGetSendingRSSI(); - return result; -} - -int16_t transportHALGetReceivingRSSI(void) -{ - int16_t result = transportGetReceivingRSSI(); - return result; -} - -int16_t transportHALGetSendingSNR(void) -{ - int16_t result = transportGetSendingSNR(); - return result; -} - -int16_t transportHALGetReceivingSNR(void) -{ - int16_t result = transportGetReceivingSNR(); - return result; -} - -int16_t transportHALGetTxPowerPercent(void) -{ - int16_t result = transportGetTxPowerPercent(); - return result; -} - -bool transportHALSetTxPowerPercent(const uint8_t powerPercent) -{ - bool result = transportSetTxPowerPercent(powerPercent); - return result; -} - -int16_t transportHALGetTxPowerLevel(void) -{ - int16_t result = transportGetTxPowerLevel(); - return result; -} diff --git a/lib/MySensors/hal/transport/MyTransportHAL.h b/lib/MySensors/hal/transport/MyTransportHAL.h deleted file mode 100644 index a9ad6d84..00000000 --- a/lib/MySensors/hal/transport/MyTransportHAL.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * TransportHAL debug log messages: - * - * |E| SYS | SUB | Message | Comment - * |-|-----|-------|----------------------------|--------------------------------------------------------------------- - * | | THA | INIT | | Initialize transportHAL - * | | THA | INIT | PSK=%%s | Load PSK for transport encryption (%AES) - * | | THA | SAD | ADDR=%%d | Set transport address (ADDR) - * | | THA | GAD | ADDR=%%d | Get trnasport address (ADDR) - * | | THA | DATA | AVAIL | Message available - * | | THA | SAN | RES=%%d | Transport sanity check, result (RES) - * | | THA | RCV | MSG=%%s | Receive message (MSG) - * | | THA | RCV | DECRYPT | Decrypt received message - * | | THA | RCV | PLAIN=%%s | Decrypted message (PLAIN) - * |!| THA | RCV | PVER=%%d | Message protocol version (PVER) mismatch - * |!| THA | RCV | LEN=%%d,EXP=%%d | Invalid message length (LEN), exptected length (EXP) - * | | THA | RCV | MSG LEN=%%d | Length of received message (LEN) - * | | THA | SND | MSG=%%s | Send message (MSG) - * | | THA | SND | ENCRYPT | Encrypt message to send (%AES) - * | | THA | SND | CIP=%%s | Ciphertext of encypted message (CIP) - * | | THA | SND | MSG LEN=%%d,RES=%%d | Sending message with length (LEN), result (RES) - * - * - */ - -#ifndef MyTransportHAL_h -#define MyTransportHAL_h - -#define INVALID_SNR ((int16_t)-256) //!< INVALID_SNR -#define INVALID_RSSI ((int16_t)-256) //!< INVALID_RSSI -#define INVALID_PERCENT ((int16_t)-100) //!< INVALID_PERCENT -#define INVALID_LEVEL ((int16_t)-256) //!< INVALID_LEVEL - -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -#if defined(MY_RADIO_NRF5_ESB) -#error Receive message buffering not supported for NRF5 radio! Please define MY_NRF5_RX_BUFFER_SIZE -#endif -#if defined(MY_RADIO_RFM69) -#error Receive message buffering not supported for RFM69! -#endif -#if defined(MY_RADIO_RFM95) -#error Receive message buffering not supported for RFM95! -#endif -#if defined(MY_RS485) -#error Receive message buffering not supported for RS485! -#endif -#elif defined(MY_RX_MESSAGE_BUFFER_SIZE) -#error Receive message buffering requires message buffering feature enabled! -#endif - -/** -* @brief Signal report selector -*/ -typedef enum { - SR_RX_RSSI, //!< SR_RX_RSSI - SR_TX_RSSI, //!< SR_TX_RSSI - SR_RX_SNR, //!< SR_RX_SNR - SR_TX_SNR, //!< SR_TX_SNR - SR_TX_POWER_LEVEL, //!< SR_TX_POWER_LEVEL - SR_TX_POWER_PERCENT, //!< SR_TX_POWER_PERCENT - SR_UPLINK_QUALITY, //!< SR_UPLINK_QUALITY - SR_NOT_DEFINED //!< SR_NOT_DEFINED -} signalReport_t; - - -/** -* @brief Initialize transport HW -* @return true if initialization successful -*/ -bool transportHALInit(void); -/** -* @brief Set node address -*/ -void transportHALSetAddress(const uint8_t address); -/** -* @brief Retrieve node address -*/ -uint8_t transportHALGetAddress(void); -/** -* @brief Send message -* @param to recipient -* @param data message to be sent -* @param len length of message (header + payload) -* @param noACK do not wait for ACK -* @return true if message sent successfully -*/ -bool transportHALSend(const uint8_t nextRecipient, const MyMessage *outMsg, const uint8_t len, - const bool noACK); -/** -* @brief Verify if RX FIFO has pending messages -* @return true if message available in RX FIFO -*/ -bool transportHALDataAvailable(void); -/** -* @brief Sanity check for transport: is transport HW still responsive? -* @return true if transport HW is ok -*/ -bool transportHALSanityCheck(void); -/** -* @brief Receive message from FIFO -* @param inMsg -* @param msgLength length of received message (header + payload) -* @return True if valid message received -*/ -bool transportHALReceive(MyMessage *inMsg, uint8_t *msgLength); -/** -* @brief Power down transport HW (if corresponding MY_XYZ_POWER_PIN defined) -*/ -void transportHALPowerDown(void); -/** -* @brief Power up transport HW (if corresponding MY_XYZ_POWER_PIN defined) -*/ -void transportHALPowerUp(void); -/** -* @brief Set transport HW to sleep (no power down) -*/ -void transportHALSleep(void); -/** -* @brief Set transport HW to standby -*/ -void transportHALStandBy(void); -/** -* @brief transportGetSendingRSSI -* @return RSSI of outgoing message (via ACK packet) -*/ -int16_t transportHALGetSendingRSSI(void); -/** -* @brief transportGetReceivingRSSI -* @return RSSI of incoming message -*/ -int16_t transportHALGetReceivingRSSI(void); -/** -* @brief transportGetSendingSNR -* @return SNR of outgoing message (via ACK packet) -*/ -int16_t transportHALGetSendingSNR(void); -/** -* @brief transportGetReceivingSNR -* @return SNR of incoming message -*/ -int16_t transportHALGetReceivingSNR(void); -/** -* @brief transportGetTxPowerPercent -* @return TX power level in percent -*/ -int16_t transportHALGetTxPowerPercent(void); -/** -* @brief transportSetTxPowerPercent -* @param powerPercent power level in percent -* @return True if power level set -*/ -bool transportHALSetTxPowerPercent(const uint8_t powerPercent); -/** -* @brief transportGetTxPowerLevel -* @return TX power in dBm -*/ -int16_t transportHALGetTxPowerLevel(void); - -#endif // MyTransportHAL_h diff --git a/lib/MySensors/hal/transport/NRF5_ESB/MyTransportNRF5_ESB.cpp b/lib/MySensors/hal/transport/NRF5_ESB/MyTransportNRF5_ESB.cpp deleted file mode 100644 index af403b07..00000000 --- a/lib/MySensors/hal/transport/NRF5_ESB/MyTransportNRF5_ESB.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Copyright (C) 2017 Frank Holtz - * Full contributor list: - * https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "hal/transport/NRF5_ESB/driver/Radio.h" -#include "hal/transport/NRF5_ESB/driver/Radio_ESB.h" - -#include "drivers/CircularBuffer/CircularBuffer.h" - -bool transportInit(void) -{ - return NRF5_ESB_initialize(); -} - -void transportSetAddress(const uint8_t address) -{ - NRF5_ESB_setNodeAddress(address); - NRF5_ESB_startListening(); -} - -uint8_t transportGetAddress(void) -{ - return NRF5_ESB_getNodeID(); -} - -bool transportSend(const uint8_t to, const void *data, const uint8_t len, const bool noACK) -{ - return NRF5_ESB_sendMessage(to, data, len, noACK); -} - -bool transportDataAvailable(void) -{ - return NRF5_ESB_isDataAvailable(); -} - -bool transportSanityCheck(void) -{ - return NRF5_ESB_sanityCheck(); -} - -uint8_t transportReceive(void *data) -{ - uint8_t len = 0; - len = NRF5_ESB_readMessage(data); - return len; -} - -void transportPowerDown(void) -{ - NRF5_ESB_powerDown(); -} - -void transportPowerUp(void) -{ - NRF5_ESB_powerUp(); -} - -void transportSleep(void) -{ - NRF5_ESB_sleep(); -} - -void transportStandBy(void) -{ - NRF5_ESB_standBy(); -} - -int16_t transportGetSendingRSSI(void) -{ - return NRF5_ESB_getSendingRSSI(); -} - -int16_t transportGetReceivingRSSI(void) -{ - return NRF5_ESB_getReceivingRSSI(); -} - -int16_t transportGetSendingSNR(void) -{ - return INVALID_SNR; -} - -int16_t transportGetReceivingSNR(void) -{ - return INVALID_SNR; -} - -int16_t transportGetTxPowerPercent(void) -{ - return NRF5_getTxPowerPercent(); -} - -int16_t transportGetTxPowerLevel(void) -{ - return static_cast(NRF5_getTxPowerLevel()); -} - -bool transportSetTxPowerPercent(const uint8_t powerPercent) -{ - return NRF5_setTxPowerPercent(powerPercent); -} diff --git a/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio.cpp b/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio.cpp deleted file mode 100644 index 381064b3..00000000 --- a/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "Radio.h" - -int16_t NRF5_getTxPowerPercent(void) -{ - // NRF5_PA_MAX = 100% NRF5_PA_MIN=0% - int16_t dbm = NRF5_getTxPowerLevel(); - int16_t dbm_diff = ((int8_t)NRF5_PA_MAX-(int8_t)NRF5_PA_MIN); - int16_t dbm_min = (int8_t)NRF5_PA_MIN; - return ((dbm-dbm_min)*100)/dbm_diff; -} - -int16_t NRF5_getTxPowerLevel(void) -{ - return (int8_t)NRF_RADIO->TXPOWER; -} - -bool NRF5_setTxPowerPercent(const uint8_t powerPercent) -{ - /* Current mapping: - * NRF51/NRF52822: - * 0.. 2% -> -40dBm (0%) - * 3..56% -> -16dBm (54%) - * 57..65% -> -12dBm (63%) - * 66..72% -> -8dBm (72%) - * 75..84% -> -4dBm (81%) - * 85..95% -> 0dBm (90%) - * NRF51 96..100%-> 4dBm (100%) - * NRF52 96..99% -> 3dBm (97%) - * NRF52 100% -> 4dBm (100%) - */ - - // Calculate dbm level - int16_t dbm_diff = ((int8_t)NRF5_PA_MAX-(int8_t)NRF5_PA_MIN); - int16_t dbm_min = (int8_t)NRF5_PA_MIN; - int8_t dbm = ((dbm_diff * powerPercent)/100)+dbm_min; - if (dbm >= (int8_t)NRF5_PA_MAX) { - NRF_RADIO->TXPOWER = NRF5_PA_MAX; - return true; - } - if (dbm > 1) { -#ifdef RADIO_TXPOWER_TXPOWER_Pos2dBm - // NRF52840 - NRF_RADIO->TXPOWER = dbm; -#elif defined(NRF51) - // nRF51x22 - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Pos4dBm; -#else - // NRF52822 - if (dbm > 3) { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Pos4dBm; - } else { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Pos3dBm; - } -#endif - return true; - } - /* duplicate condition - if (dbm > (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_0dBm; - return true; - } - */ - if (dbm > (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_0dBm; - return true; - } - if (dbm > (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg4dBm; - return true; - } - if (dbm > (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg8dBm; - return true; - } - if (dbm > (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg12dBm; - return true; - } - if (dbm > (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg16dBm; - return true; - } - if (dbm > (int8_t)NRF5_PA_MIN) { - NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg16dBm; - return true; - } - - NRF_RADIO->TXPOWER = NRF5_PA_MIN; - return true; -} diff --git a/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio.h b/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio.h deleted file mode 100644 index e4ac5dce..00000000 --- a/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of - * the - * network topology allowing messages to be routed to nodes. - * - * Created by Frank Holtz - * Copyright (C) 2017 Frank Holtz - * Full contributor list: - * https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef __NRF_RADIO_H__ -#define __NRF_RADIO_H__ - -#if !defined(ARDUINO_ARCH_NRF5) -#error "NRF5 Radio is not supported for this platform." -#endif - -#include -#include -#include -#include - -// Timer to use -#define NRF5_RADIO_TIMER NRF_TIMER0 -#define NRF5_RADIO_TIMER_IRQ_HANDLER TIMER0_IRQHandler -#define NRF5_RADIO_TIMER_IRQN TIMER0_IRQn - -// debug -#if defined(MY_DEBUG_VERBOSE_NRF5_ESB) -#define NRF5_RADIO_DEBUG(x, ...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< DEBUG -#else -#define NRF5_RADIO_DEBUG(x, ...) //!< DEBUG null -#endif - -// tx power -typedef enum { -#ifdef NRF51 - NRF5_PA_MIN = RADIO_TXPOWER_TXPOWER_Neg30dBm, // Deprecated -#else - NRF5_PA_MIN = RADIO_TXPOWER_TXPOWER_Neg40dBm, -#endif - NRF5_PA_LOW = RADIO_TXPOWER_TXPOWER_Neg16dBm, - NRF5_PA_HIGH = RADIO_TXPOWER_TXPOWER_0dBm, -#ifdef RADIO_TXPOWER_TXPOWER_Pos9dBm - // nRF52840 - NRF5_PA_MAX = RADIO_TXPOWER_TXPOWER_Pos9dBm, -#else - // nRF51x22/nRF52822 - NRF5_PA_MAX = RADIO_TXPOWER_TXPOWER_Pos4dBm, -#endif -} nrf5_txpower_e; - -// Radio mode (Data rate) -typedef enum { - NRF5_1MBPS = RADIO_MODE_MODE_Nrf_1Mbit, - NRF5_2MBPS = RADIO_MODE_MODE_Nrf_2Mbit, - NRF5_250KBPS = RADIO_MODE_MODE_Nrf_250Kbit, // Deprecated!!! - NRF5_BLE_1MBPS = RADIO_MODE_MODE_Ble_1Mbit, -} nrf5_mode_e; - -int16_t NRF5_getTxPowerPercent(void); -int16_t NRF5_getTxPowerLevel(void); -bool NRF5_setTxPowerPercent(const uint8_t powerPercent); - - -#endif // __NRF_RADIO_H__ diff --git a/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio_ESB.cpp b/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio_ESB.cpp deleted file mode 100644 index 538b53d1..00000000 --- a/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio_ESB.cpp +++ /dev/null @@ -1,710 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors formrs a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of - * the - * network topology allowing messages to be routed to nodes. - * - * Created by Frank Holtz - * Copyright (C) 2017 Frank Holtz - * Full contributor list: - * https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "Radio.h" -#include "Radio_ESB.h" -#include "hal/architecture/NRF5/MyHwNRF5.h" -#include "drivers/CircularBuffer/CircularBuffer.h" -#include - -// internal functions -static uint8_t reverse_byte(uint8_t address); -inline void _stopTimer(); -inline void _stopACK(); - -// RX Buffer -static NRF5_ESB_Packet rx_circular_buffer_buffer[MY_NRF5_ESB_RX_BUFFER_SIZE]; -// Poiter to rx circular buffer -static NRF5_ESB_Packet rx_buffer; -// Circular buffer -static CircularBuffer -rx_circular_buffer(rx_circular_buffer_buffer, MY_NRF5_ESB_RX_BUFFER_SIZE); -// Dedect duplicate packages for every pipe available -static volatile uint32_t package_ids[8]; - -// TX Buffer -static NRF5_ESB_Packet tx_buffer; -// remaining TX retries -static volatile int8_t tx_retries; -// PID number for ACK -static volatile int8_t ack_pid; -// Flag for ack received -static volatile bool ack_received; -// Flag for end TX event -static volatile bool events_end_tx; -// Last RSSI sample provided by NRF5_ESB_readMessage -static volatile int16_t rssi_rx; -// Last RSSI sample by last package -static volatile int16_t rssi_tx; -// Buffer node address -static uint8_t node_address = 0; -// TX power level -static int8_t tx_power_level = (MY_NRF5_ESB_PA_LEVEL << RADIO_TXPOWER_TXPOWER_Pos); - -// Initialize radio unit -static bool NRF5_ESB_initialize() -{ - NRF5_RADIO_DEBUG(PSTR("NRF5:INIT:ESB\n")); - -#if defined(SOFTDEVICE_PRESENT) - // Disable the SoftDevice; requires NRF5 SDK available - sd_softdevice_disable(); -#endif - - // Power on radio unit - NRF_RADIO->POWER = 1; - - // Disable shorts - NRF_RADIO->SHORTS = 0; - - // Disable radio - NRF_RADIO->TASKS_DISABLE = 1; - - // Enable radio interrupt - NVIC_SetPriority(RADIO_IRQn, 1); - NVIC_ClearPendingIRQ(RADIO_IRQn); - NVIC_EnableIRQ(RADIO_IRQn); - - // Enable timer interrupt - NVIC_SetPriority(NRF5_RADIO_TIMER_IRQN, 2); - NVIC_ClearPendingIRQ(NRF5_RADIO_TIMER_IRQN); - NVIC_EnableIRQ(NRF5_RADIO_TIMER_IRQN); - - // Clear all events - NRF_RADIO->EVENTS_ADDRESS = 0; - NRF_RADIO->EVENTS_BCMATCH = 0; - NRF_RADIO->EVENTS_DEVMATCH = 0; - NRF_RADIO->EVENTS_DEVMISS = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->EVENTS_PAYLOAD = 0; - NRF_RADIO->EVENTS_READY = 0; - NRF_RADIO->EVENTS_RSSIEND = 0; - - // Disable all interrupts - NRF_RADIO->INTENCLR = (uint32_t)~0; - - // Select interrupt events - NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk | RADIO_INTENSET_BCMATCH_Msk; - - // Configure radio parameters: tx power - NRF_RADIO->TXPOWER = tx_power_level; - - // Configure radio parameters: radio channel - NRF_RADIO->FREQUENCY = MY_NRF5_ESB_CHANNEL; - - // Configure radio parameters: data rate - NRF_RADIO->MODE = MY_NRF5_ESB_MODE; - -#ifdef NRF52 - // Configure nRF52 specific mode register - NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos) | - (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos); -#endif - - // Configure radio parameters: CRC16 - NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); - NRF_RADIO->CRCINIT = 0xFFFFUL; - NRF_RADIO->CRCPOLY = 0x11021UL; - - // Radio address config - uint8_t address[MY_NRF5_ESB_ADDR_WIDTH] = {MY_NRF5_ESB_BASE_RADIO_ID}; - - // Configure addresses - NRF_RADIO->PREFIX0 = (NRF5_ESB_NODE_ADDR_MSK | reverse_byte(node_address) << - (NRF5_ESB_NODE_ADDR << 5)); - NRF_RADIO->BASE0 = reverse_byte(address[1]) << 24 | - reverse_byte(address[2]) << 16 | - reverse_byte(address[3]) << 8 | reverse_byte(address[4]); - NRF_RADIO->BASE1 = reverse_byte(address[1]) << 24 | - reverse_byte(address[2]) << 16 | - reverse_byte(address[3]) << 8 | reverse_byte(address[4]); - NRF_RADIO->PREFIX1 = NRF5_ESB_TX_ADDR_MSK; // Broadcast and send address - - // Enable listening on Node and BC address - NRF_RADIO->RXADDRESSES = (1 << NRF5_ESB_NODE_ADDR) | (1 << NRF5_ESB_BC_ADDR); - - // Packet configuration for nRF24 compatibility - NRF_RADIO->PCNF0 = (6 << RADIO_PCNF0_LFLEN_Pos) | // 6 Bits length field - (0 << RADIO_PCNF0_S0LEN_Pos) | // No S0 -#ifdef RADIO_PCNF0_S1INCL_Pos - (1 << RADIO_PCNF0_S1INCL_Pos) | // Force include S1 in RAM -#endif - (3 << RADIO_PCNF0_S1LEN_Pos); // 3 Bits S1 (NOACK and PID) - - // Packet configuration - NRF_RADIO->PCNF1 = - (MAX_MESSAGE_SIZE << RADIO_PCNF1_MAXLEN_Pos) | // maximum length - (0 << RADIO_PCNF1_STATLEN_Pos) | // minimum message length - ((MY_NRF5_ESB_ADDR_WIDTH - 1) << RADIO_PCNF1_BALEN_Pos) | // Set base address length - (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | // Big endian - (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos); // Disable whitening - - // HINT: Fast ramp up can enabled here. Needs more code on other lines - // Fast ramp up isn't supported by nRF24 and NRF51 series. - - // Set bitcounter to trigger interrupt after ACK bit - NRF_RADIO->BCC = NRF5_ESB_BITCOUNTER; - -#ifdef NRF51 - // Enable timer - NRF5_RADIO_TIMER->POWER = 1; -#endif - // Stop timer, if running - _stopTimer(); - // Prepare timer running at 1 MHz/1us - NRF5_RADIO_TIMER->PRESCALER = 4; - // Timer mode - NRF5_RADIO_TIMER->MODE = TIMER_MODE_MODE_Timer; - // in 16 Bit mode - NRF5_RADIO_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos; - // Stop timer when CC0 reached - NRF5_RADIO_TIMER->SHORTS = - TIMER_SHORTS_COMPARE3_CLEAR_Msk | TIMER_SHORTS_COMPARE3_STOP_Msk; - // Reset timer - NRF5_RADIO_TIMER->TASKS_CLEAR = 1; - - // Reset compare events -#ifdef NRF51 - for (uint8_t i=0; i<4; i++) { -#else - for (uint8_t i=0; i<6; i++) { -#endif - NRF5_RADIO_TIMER->EVENTS_COMPARE[i] = 0; - } - - // Enable interrupt - NRF5_RADIO_TIMER->INTENSET = TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos; - -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - intcntr_bcmatch=0; - intcntr_ready=0; - intcntr_end=0; -#endif - - return true; -} - -static void NRF5_ESB_powerDown() -{ - NRF5_RADIO_DEBUG(PSTR("NRF5:PD\n")); - - // Disable inerrupt - NVIC_DisableIRQ(RADIO_IRQn); - NVIC_DisableIRQ(NRF5_RADIO_TIMER_IRQN); - - // Clear PPI - NRF_PPI->CHENCLR = NRF5_ESB_PPI_BITS; - - // Save power level - tx_power_level = NRF_RADIO->TXPOWER; - - // Power off readio unit - NRF_RADIO->POWER = 0; - - // Shutdown timer - NRF5_RADIO_TIMER->TASKS_SHUTDOWN = 1; -#ifdef NRF51 - // Power off timer - NRF5_RADIO_TIMER->POWER = 0; -#endif -} - -static void NRF5_ESB_powerUp() -{ - NRF5_ESB_initialize(); -} - -static void NRF5_ESB_sleep() -{ - NRF5_RADIO_DEBUG(PSTR("NRF5:SLP\n")); - - // Disable shorts - NRF_RADIO->SHORTS = 0; - - // Disable radio - NRF_RADIO->TASKS_DISABLE = 1; -} - -static void NRF5_ESB_standBy() -{ - NRF5_RADIO_DEBUG(PSTR("NRF5:SBY\n")); - NRF5_ESB_startListening(); -} - -static bool NRF5_ESB_sanityCheck() -{ - // always true - return true; -} - -static void NRF5_ESB_setNodeAddress(const uint8_t address) -{ - node_address = address; - NRF_RADIO->PREFIX0 = (NRF_RADIO->PREFIX0 & NRF5_ESB_NODE_ADDR_MSK) | - reverse_byte(node_address) << (NRF5_ESB_NODE_ADDR << 5); -} - -static uint8_t NRF5_ESB_getNodeID() -{ - return reverse_byte((NRF_RADIO->PREFIX0 & NRF5_ESB_NODE_ADDR_MSK) >> (NRF5_ESB_NODE_ADDR << 5)); -} - -static void NRF5_ESB_startListening() -{ - NRF5_RADIO_DEBUG(PSTR("NRF5:STL\n")); - - // Check if radio is initialized - if (NRF_RADIO->POWER == 0) { - NRF5_ESB_initialize(); - } - -#ifdef NRF52 - // Fix PAN#102 and PAN#106 - *((volatile uint32_t *)0x40001774) = (*((volatile uint32_t *)0x40001774) & 0xFFFFFFFE) | 0x01000000; -#endif - - // Enable Ready interrupt - NRF_RADIO->INTENSET = RADIO_INTENSET_READY_Msk; - - // Enable RX when ready, Enable RX after disabling task - NRF_RADIO->SHORTS = NRF5_ESB_SHORTS_RX; - - // Switch to RX - if (NRF_RADIO->STATE == RADIO_STATE_STATE_Disabled) { - NRF_RADIO->TASKS_RXEN = 1; - } else { - NRF_RADIO->TASKS_DISABLE = 1; - } -} - -static bool NRF5_ESB_isDataAvailable() -{ - return rx_circular_buffer.available() > 0; -} - -static uint8_t NRF5_ESB_readMessage(void *data) -{ - uint8_t ret = 0; - - // get content from rx buffer - NRF5_ESB_Packet *buffer = rx_circular_buffer.getBack(); - // Nothing to read? - if (buffer != NULL) { - // copy content - memcpy(data, buffer->data, buffer->len); - ret = buffer->len; - rssi_rx = 0-buffer->rssi; - - // Debug message -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - NRF5_RADIO_DEBUG(PSTR("NRF5:RX:LEN=%" PRIu8 ",NOACK=%" PRIu8 ",PID=%" PRIu8 ",RSSI=%" PRIi16 ",RX=%" - PRIu32 "\n"), - buffer->len, buffer->noack, buffer->pid, rssi_rx, buffer->rxmatch); -#endif - - // release buffer - rx_circular_buffer.popBack(); - } - - return ret; -} - -void NRF5_ESB_endtx(); -void NRF5_ESB_starttx() -{ - if (tx_retries > 0) { - // Prevent radio to write into TX memory while receiving - if (NRF_RADIO->PACKETPTR != (uint32_t)&tx_buffer) { - // Disable shorts - NRF_RADIO->SHORTS = 0; - // Disable radio - NRF_RADIO->TASKS_DISABLE = 1; - } - - // Mark TX as unfinised - events_end_tx = false; - - // Configure TX address to address at index NRF5_ESB_TX_ADDR - NRF_RADIO->TXADDRESS = NRF5_ESB_TX_ADDR; - - // Enable TX when ready, Enable TX after disabling task - NRF_RADIO->SHORTS = NRF5_ESB_SHORTS_TX; - - // reset timer - NRF_RESET_EVENT(NRF5_RADIO_TIMER->EVENTS_COMPARE[3]); - _stopTimer(); - NRF5_RADIO_TIMER->TASKS_CLEAR = 1; - // Set retransmit time - NRF5_RADIO_TIMER->CC[3] = NRF5_ESB_ARD - NRF5_ESB_RAMP_UP_TIME; - // Set radio disable time to ACK_WAIT time - NRF5_RADIO_TIMER->CC[1] = NRF5_ESB_ACK_WAIT; - - /** Configure PPI (Programmable peripheral interconnect) */ - // Start timer on END event - NRF_PPI->CH[NRF5_ESB_PPI_TIMER_START].EEP = (uint32_t)&NRF_RADIO->EVENTS_END; - NRF_PPI->CH[NRF5_ESB_PPI_TIMER_START].TEP = (uint32_t)&NRF5_RADIO_TIMER->TASKS_START; -#ifdef NRF52 - NRF_PPI->FORK[NRF5_ESB_PPI_TIMER_START].TEP = 0; -#endif - -#ifndef NRF5_ESB_USE_PREDEFINED_PPI - // Disable Radio after CC[1] - NRF_PPI->CH[NRF5_ESB_PPI_TIMER_RADIO_DISABLE].EEP = (uint32_t)&NRF5_RADIO_TIMER->EVENTS_COMPARE[1]; - NRF_PPI->CH[NRF5_ESB_PPI_TIMER_RADIO_DISABLE].TEP = (uint32_t)&NRF_RADIO->TASKS_DISABLE; -#ifdef NRF52 - NRF_PPI->CH[NRF5_ESB_PPI_TIMER_RADIO_DISABLE].TEP = 0; -#endif -#endif - - // Set PPI - NRF_PPI->CHENSET = NRF5_ESB_PPI_BITS; - - // Disable Ready interrupt - NRF_RADIO->INTENCLR = RADIO_INTENSET_READY_Msk; - - // Set buffer - NRF_RADIO->PACKETPTR = (uint32_t)&tx_buffer; - - // Switch to TX - if (NRF_RADIO->STATE == RADIO_STATE_STATE_Disabled) { - NRF_RADIO->TASKS_TXEN = 1; - } else { - NRF_RADIO->TASKS_DISABLE = 1; - } - } else { - // finised TX - NRF5_ESB_endtx(); - } - tx_retries--; -} - -void NRF5_ESB_endtx() -{ - // Clear PPI - NRF_PPI->CHENCLR = NRF5_ESB_PPI_BITS; - // Enable Ready interrupt - NRF_RADIO->INTENSET = RADIO_INTENSET_READY_Msk; - // Stop Timer - _stopTimer(); - // Mark TX as end - events_end_tx = true; - // Debug output -#ifdef NRF5_ESB_DEBUG_INT_TX_END - NRF5_RADIO_DEBUG(PSTR("NRF5:INT:ENDTX\n")); -#endif -} - -static bool NRF5_ESB_sendMessage(uint8_t recipient, const void *buf, uint8_t len, const bool noACK) -{ - NRF5_RADIO_DEBUG(PSTR("NRF5:SND:TO=%" PRIu8 ",LEN=%" PRIu8 ",PID=%" PRIu8 ",NOACK=%" PRIu8 "\n"), - recipient, len, tx_buffer.pid, - tx_buffer.noack); // send message - // Check if radio is initialized - if (NRF_RADIO->POWER == 0) { - NRF5_ESB_initialize(); - } - - // check length and truncate data - if (len > MAX_MESSAGE_SIZE) { - len = MAX_MESSAGE_SIZE; - } - - // copy data to tx_buffer - memcpy(&tx_buffer.data[0], buf, len); - - // build metadata - tx_buffer.len = len; -#ifndef MY_NRF5_ESB_REVERSE_ACK_TX - tx_buffer.noack = noACK || recipient==BROADCAST_ADDRESS; -#else - // reverse the noack bit - tx_buffer.noack = !(noACK || recipient==BROADCAST_ADDRESS); -#endif - tx_buffer.pid++; - - // Calculate number of retries - if (recipient == BROADCAST_ADDRESS) { - tx_retries = NRF5_ESB_BC_ARC; - } else { - tx_retries = ((noACK == false)?(NRF5_ESB_ARC_ACK):(NRF5_ESB_ARC_NOACK)); - } - int8_t tx_retries_start = tx_retries; - ack_received = false; - - // configure TX address - NRF_RADIO->PREFIX1 = (NRF_RADIO->PREFIX1 & NRF5_ESB_TX_ADDR_MSK) | - (reverse_byte(recipient) << (NRF5_ESB_TX_ADDR - 4)); - - // Enable listening on Node, BC and TX address - NRF_RADIO->RXADDRESSES = (1 << NRF5_ESB_NODE_ADDR) | (1 << NRF5_ESB_BC_ADDR) | - (1 << NRF5_ESB_TX_ADDR); - - // Set RSSI to invalid - rssi_tx = INVALID_RSSI; - - NRF5_ESB_starttx(); - - // Wait for end of transmission -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - uint32_t wakeups = 0; -#endif - while (events_end_tx == false) { - // Power off CPU until next interrupt - hwSleep(); - // hwWaitForInterrupt(); -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - wakeups++; -#endif - } - - // Calculate RSSI - if (rssi_tx == INVALID_RSSI) { - // calculate pseudo-RSSI based on retransmission counter (ARC) - // min -104dBm at 250kBps - // Arbitrary definition: ARC 0 == -29, ARC 15 = -104 - rssi_tx = (-29 - (8 * (tx_retries_start - tx_retries))); - } - - // Enable listening on Node and BC address - NRF_RADIO->RXADDRESSES = (1 << NRF5_ESB_NODE_ADDR) | (1 << NRF5_ESB_BC_ADDR); - -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - NRF5_RADIO_DEBUG(PSTR("NRF5:SND:END=%" PRIu8 ",ACK=%" PRIu8 ",RTRY=%" PRIi8 ",RSSI=%" PRIi16 - ",WAKE=%" PRIu32 "\n"), - events_end_tx, ack_received, tx_retries_start - tx_retries, rssi_tx, wakeups); -#endif - - - return ack_received; -}; - -static int16_t NRF5_ESB_getSendingRSSI() -{ - return rssi_tx; -} - -static int16_t NRF5_ESB_getReceivingRSSI() -{ - return rssi_rx; -} - -/* - * Internal helper functions - */ - -// Reverse a byte for address -static uint8_t reverse_byte(uint8_t address) -{ -#if __CORTEX_M >= (0x01U) - return __REV(__RBIT(address)); -#else - address = ((address * 0x0802LU & 0x22110LU) | (address * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; -#endif - return address; -} - -inline void _stopTimer() -{ - // Stop timer - NRF5_RADIO_TIMER->TASKS_STOP = 1; - // NRF52 PAN#78 - NRF5_RADIO_TIMER->TASKS_SHUTDOWN = 1; -} - -inline void _stopACK() -{ - // Enable RX when ready, Enable RX after disabling task - NRF_RADIO->SHORTS = NRF5_ESB_SHORTS_RX; - - // Start disabling radio -> switch to rx by shorts - NRF_RADIO->TASKS_DISABLE = 1; -} - -// Calculate time to transmit an byte in µs as bit shift -> 2^X -static inline uint8_t NRF5_ESB_byte_time() -{ - if ((MY_NRF5_ESB_MODE == NRF5_1MBPS) or - (MY_NRF5_ESB_MODE == NRF5_BLE_1MBPS)) { - return (3); - } else if (MY_NRF5_ESB_MODE == NRF5_2MBPS) { - return (2); - } else if (MY_NRF5_ESB_MODE == NRF5_250KBPS) { - return (5); - } -} - -extern "C" { - /** Radio Interrupt handler */ - void RADIO_IRQHandler() - { - /** Bitcounter event is used to switch between RX/TX - * In RX mode, when an ACK required packet is received, switch to TX, - * elsewhere start RX again. - * In TX mode switch always to RX. - */ - if (NRF_RADIO->EVENTS_BCMATCH == 1) { - NRF_RESET_EVENT(NRF_RADIO->EVENTS_BCMATCH); -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - intcntr_bcmatch++; -#endif - // Disable bitcounter - NRF_RADIO->TASKS_BCSTOP = 1; - - // In RX mode -> prepare ACK or RX - if (NRF_RADIO->STATE == RADIO_STATE_STATE_Rx) { - // Send ACK only for node address, don't care about the ACK bit to handle bad nRF24 clones - if (NRF_RADIO->RXMATCH == NRF5_ESB_NODE_ADDR) { - // Send ACK after END, an empty packet is provided in READY event - NRF_RADIO->SHORTS = NRF5_ESB_SHORTS_RX_TX; - } else { - // No ACK -> Start RX after END - NRF_RADIO->SHORTS = NRF5_ESB_SHORTS_RX; - } - - // Handle incoming ACK packet - if (NRF_RADIO->RXMATCH == NRF5_ESB_TX_ADDR) { - /** Calculate time to switch radio off - * This is an ACK packet, the radio is disabled by Timer - * event after CC[1], calculate the time switching of the - * radio. - */ - // Read current timer value - NRF5_RADIO_TIMER->TASKS_CAPTURE[1] = 1; - - // Set Timer compare register 0 to end of packet (len+CRC) - NRF5_RADIO_TIMER->CC[1] += ((rx_buffer.len + 3) << NRF5_ESB_byte_time()); - } - } else { - // Current mode is TX: - // After TX the Radio has to be always in RX mode to - // receive ACK or start implicit listen mode after send. - NRF_RADIO->SHORTS = NRF5_ESB_SHORTS_TX_RX; - // HINT: Fast ramp up can enabled here. Needs more code on other lines - } - } - - /** Ready event is generated before RX starts - * An free rx buffer is allocated or radio is disabled on failures - */ - if (NRF_RADIO->EVENTS_READY == 1) { - NRF_RESET_EVENT(NRF_RADIO->EVENTS_READY); -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - intcntr_ready++; -#endif - // Configure DMA target address - NRF_RADIO->PACKETPTR = (uint32_t)&rx_buffer; - - /* Don't care about if next packet RX or ACK, - * prepare current rx_buffer to send an ACK */ - - // Set outgoing address to node address for ACK packages - NRF_RADIO->TXADDRESS = NRF5_ESB_NODE_ADDR; - } - - /** This event is generated after TX or RX finised - */ - if (NRF_RADIO->EVENTS_END == 1) { - NRF_RESET_EVENT(NRF_RADIO->EVENTS_END); -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - intcntr_end++; -#endif - - // Enable ACK bitcounter for next packet - NRF_RADIO->BCC = NRF5_ESB_BITCOUNTER; - - // End of RX packet - if ((NRF_RADIO->STATE == RADIO_STATE_STATE_Rx) or - (NRF_RADIO->STATE == RADIO_STATE_STATE_RxIdle) or - (NRF_RADIO->STATE == RADIO_STATE_STATE_RxDisable) or - (NRF_RADIO->STATE == RADIO_STATE_STATE_TxRu)) { - if (NRF_RADIO->CRCSTATUS) { - // Ensure no ACK package is received - if (NRF_RADIO->RXMATCH != NRF5_ESB_TX_ADDR) { - // calculate a package id - uint32_t pkgid = rx_buffer.pid << 16 | NRF_RADIO->RXCRC; - if (pkgid != package_ids[NRF_RADIO->RXMATCH]) { - // correct package -> store id to dedect duplicates - package_ids[NRF_RADIO->RXMATCH] = pkgid; - rx_buffer.rssi = NRF_RADIO->RSSISAMPLE; -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - // Store debug data - rx_buffer.rxmatch = NRF_RADIO->RXMATCH; -#endif - // Push data to buffer - if (rx_circular_buffer.pushFront(&rx_buffer)) { - // Prepare ACK package - rx_buffer.data[0]=rx_buffer.rssi; - rx_buffer.len=1; // data[0] is set some lines before -#ifndef MY_NRF5_ESB_REVERSE_ACK_TX - rx_buffer.noack = 1; -#else - rx_buffer.noack = 0; -#endif - } else { - // Buffer is full - // Stop ACK - _stopACK(); - // Increment pkgid allowing receive the package again - package_ids[NRF_RADIO->RXMATCH]++; - } - } - } else { - // ACK package received, ducplicates are accepted - - // rssi value in ACK included? - if (rx_buffer.len == 1) { - rssi_tx = 0-rx_buffer.data[0]; - } - // notify TX process - ack_received = true; - // End TX - NRF5_ESB_endtx(); - } - } else { - /** Invalid CRC -> Switch back to RX, Stop sending ACK */ - _stopACK(); - } - } else { - // TX end - } - } - } - - /** Timer Interrupt Handler - * This timer is used to handle TX retransmit timing - * - */ - void NRF5_RADIO_TIMER_IRQ_HANDLER() - { - if (NRF5_RADIO_TIMER->EVENTS_COMPARE[3] == 1) { - _stopTimer(); - NRF_RESET_EVENT(NRF5_RADIO_TIMER->EVENTS_COMPARE[1]); - if (ack_received == false) { - // missing ACK, start TX again - NRF5_ESB_starttx(); - } else { - // finised TX - NRF5_ESB_endtx(); - } - } - } -} // extern "C" diff --git a/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio_ESB.h b/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio_ESB.h deleted file mode 100644 index bcd37640..00000000 --- a/lib/MySensors/hal/transport/NRF5_ESB/driver/Radio_ESB.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of - * the - * network topology allowing messages to be routed to nodes. - * - * Created by Frank Holtz - * Copyright (C) 2017 Frank Holtz - * Full contributor list: - * https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef __NRF5_ESB_H__ -#define __NRF5_ESB_H__ - -#include "Radio.h" -#include - -// Check maximum message length -#if MAX_MESSAGE_SIZE > (32) -#error "Unsupported message size. (MAX_MESSAGE_SIZE)" -#endif - -// check rx buffer size -#if MY_NRF5_ESB_RX_BUFFER_SIZE < (4) -#error "MY_NRF5_ESB_RX_BUFFER_SIZE must be greater than 3." -#endif - -/** Wait for start of an ACK packet in us - * Calculation: ramp up time + packet header (57 Bit): round to 9 Byte - * If you don't receive ACK packages, you have to increase this value. - * My measured (Arduino Uno + nRF24L01P) minimal timeouts: - * 250kbit 411us -> 182 us to ACK start - * 1MBit 205us -> 147 us - * 2MBit 173us -> 143 us - */ -#define NRF5_ESB_ACK_WAIT \ - ((NRF5_ESB_RAMP_UP_TIME << 1) + (9 << NRF5_ESB_byte_time())) - -// auto retry delay in us, don't set this value < 1500us@250kbit -#define NRF5_ESB_ARD (1500) - -// auto retry count with noACK is false -#define NRF5_ESB_ARC_ACK (15) - -// auto retry count with noACK is true -#define NRF5_ESB_ARC_NOACK (3) - -// How often broadcast messages are send -#define NRF5_ESB_BC_ARC (3) - -// Node address index -#define NRF5_ESB_NODE_ADDR (0) -#define NRF5_ESB_NODE_ADDR_MSK (0xffffff00UL) - -// TX address index -#define NRF5_ESB_TX_ADDR (4) -#define NRF5_ESB_TX_ADDR_MSK (0xffffff00UL) - -// BC address index -#define NRF5_ESB_BC_ADDR (7) -#define NRF5_ESB_BC_ADDR_MSK (0xffffffffUL) - -// Shorts for RX mode -#define NRF5_ESB_SHORTS_RX \ - (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_START_Msk | \ - RADIO_SHORTS_DISABLED_RXEN_Msk | RADIO_SHORTS_ADDRESS_BCSTART_Msk | \ - RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk) - -// Shorts for TX mode -#define NRF5_ESB_SHORTS_TX \ - (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_START_Msk | \ - RADIO_SHORTS_DISABLED_TXEN_Msk | RADIO_SHORTS_ADDRESS_BCSTART_Msk) - -// Shorts to switch from RX to TX -#define NRF5_ESB_SHORTS_RX_TX \ - (RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_TXEN_Msk | \ - RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_ADDRESS_BCSTART_Msk) - -// Shorts to switch from TX to RX -#define NRF5_ESB_SHORTS_TX_RX \ - (RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_RXEN_Msk | \ - RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_ADDRESS_BCSTART_Msk | \ - RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk) - -// PPI Channels for TX -#if (NRF5_RADIO_TIMER_IRQN != TIMER0_IRQn) -// Use two regular PPI channels -#define NRF5_ESB_PPI_TIMER_START 14 -#define NRF5_ESB_PPI_TIMER_RADIO_DISABLE 15 -#else -// Use one regular PPI channel and one predefined PPI channel -#define NRF5_ESB_USE_PREDEFINED_PPI -#define NRF5_ESB_PPI_TIMER_START 15 -#define NRF5_ESB_PPI_TIMER_RADIO_DISABLE 22 -#endif -#define NRF5_ESB_PPI_BITS \ - ((1 << NRF5_ESB_PPI_TIMER_START) | \ - (1 << NRF5_ESB_PPI_TIMER_RADIO_DISABLE)) - -/** Bitcounter for Packet Control Field length - * 6 Bits address length + 3 Bits S1 (NOACK + PID) - */ -#define NRF5_ESB_BITCOUNTER (9) - -/** ramp up time - * Time to activate radio TX or RX mode - */ -#define NRF5_ESB_RAMP_UP_TIME (140) - - -static bool NRF5_ESB_initialize(); -static void NRF5_ESB_powerDown(); -static void NRF5_ESB_powerUp(); -static void NRF5_ESB_sleep(); -static void NRF5_ESB_standBy(); -static bool NRF5_ESB_sanityCheck(); - -static void NRF5_ESB_setNodeAddress(const uint8_t address); -static uint8_t NRF5_ESB_getNodeID(); - -static void NRF5_ESB_startListening(); -static bool NRF5_ESB_isDataAvailable(); -static uint8_t NRF5_ESB_readMessage(void *data); - -static bool NRF5_ESB_sendMessage(uint8_t recipient, const void *buf, uint8_t len, const bool noACK); - -static int16_t NRF5_ESB_getSendingRSSI(); -static int16_t NRF5_ESB_getReceivingRSSI(); - -// Calculate time to transmit an byte in us as bit shift -> 2^X -static inline uint8_t NRF5_ESB_byte_time(); - -/** Structure of radio rackets - */ -typedef struct nrf5_radio_packet_s { - // structure written by radio unit - struct { - uint8_t len; - union { - uint8_t s1; - struct { - uint8_t noack : 1; - uint8_t pid : 2; - }; - }; - uint8_t data[MAX_MESSAGE_SIZE]; - int8_t rssi; - /** Debug data structure */ -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB - uint32_t rxmatch; -#endif - } -#ifndef DOXYGEN - __attribute__((packed)); -#endif -} NRF5_ESB_Packet; - -#ifdef MY_DEBUG_VERBOSE_NRF5_ESB -static uint32_t intcntr_bcmatch; -static uint32_t intcntr_ready; -static uint32_t intcntr_end; -#endif - -#endif // __NRF5_H__ diff --git a/lib/MySensors/hal/transport/RF24/MyTransportRF24.cpp b/lib/MySensors/hal/transport/RF24/MyTransportRF24.cpp deleted file mode 100644 index 3f7349ad..00000000 --- a/lib/MySensors/hal/transport/RF24/MyTransportRF24.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "hal/transport/RF24/driver/RF24.h" - -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -#include "drivers/CircularBuffer/CircularBuffer.h" - -typedef struct _transportQueuedMessage { - uint8_t m_len; // Length of the data - uint8_t m_data[MAX_MESSAGE_SIZE]; // The raw data -} transportQueuedMessage; - -/** Buffer to store queued messages in. */ -static transportQueuedMessage transportRxQueueStorage[MY_RX_MESSAGE_BUFFER_SIZE]; -/** Circular buffer, which uses the transportRxQueueStorage and administers stored messages. */ -static CircularBuffer transportRxQueue(transportRxQueueStorage, - MY_RX_MESSAGE_BUFFER_SIZE); - -static volatile uint8_t transportLostMessageCount = 0; - -static void transportRxCallback(void) -{ - // Called for each message received by radio, from interrupt context. - // This function _must_ call RF24_readMessage() to de-assert interrupt line! - if (!transportRxQueue.full()) { - transportQueuedMessage* msg = transportRxQueue.getFront(); - msg->m_len = RF24_readMessage(msg->m_data); // Read payload & clear RX_DR - (void)transportRxQueue.pushFront(msg); - } else { - // Queue is full. Discard message. - (void)RF24_readMessage(NULL); // Read payload & clear RX_DR - // Keep track of messages lost. Max 255, prevent wrapping. - if (transportLostMessageCount < 255) { - ++transportLostMessageCount; - } - } -} -#endif - -bool transportInit(void) -{ -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - RF24_registerReceiveCallback( transportRxCallback ); -#endif - return RF24_initialize(); -} - -void transportSetAddress(const uint8_t address) -{ - RF24_setNodeAddress(address); - RF24_startListening(); -} - -uint8_t transportGetAddress(void) -{ - return RF24_getNodeID(); -} - -bool transportSend(const uint8_t to, const void *data, const uint8_t len, const bool noACK) -{ - return RF24_sendMessage(to, data, len, noACK); -} - -bool transportDataAvailable(void) -{ -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - (void)RF24_isDataAvailable; // Prevent 'defined but not used' warning - return !transportRxQueue.empty(); -#else - return RF24_isDataAvailable(); -#endif -} - -bool transportSanityCheck(void) -{ - return RF24_sanityCheck(); -} - -uint8_t transportReceive(void *data) -{ - uint8_t len = 0; -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - transportQueuedMessage* msg = transportRxQueue.getBack(); - if (msg) { - len = msg->m_len; - (void)memcpy(data, msg->m_data, len); - (void)transportRxQueue.popBack(); - } -#else - len = RF24_readMessage(data); -#endif - return len; -} - -void transportSleep(void) -{ - RF24_sleep(); -} - -void transportStandBy(void) -{ - RF24_standBy(); -} - -void transportPowerDown(void) -{ - RF24_powerDown(); -} - -void transportPowerUp(void) -{ - RF24_powerUp(); -} - -int16_t transportGetSendingRSSI(void) -{ - return RF24_getSendingRSSI(); -} - -int16_t transportGetReceivingRSSI(void) -{ - // not available, only bool RPD - return INVALID_RSSI; -} - -int16_t transportGetSendingSNR(void) -{ - return INVALID_SNR; -} - -int16_t transportGetReceivingSNR(void) -{ - return INVALID_SNR; -} - -int16_t transportGetTxPowerPercent(void) -{ - return static_cast(RF24_getTxPowerPercent()); -} - -int16_t transportGetTxPowerLevel(void) -{ - return static_cast(RF24_getTxPowerLevel()); -} - -bool transportSetTxPowerPercent(const uint8_t powerPercent) -{ - return RF24_setTxPowerPercent(powerPercent); -} diff --git a/lib/MySensors/hal/transport/RF24/driver/RF24.cpp b/lib/MySensors/hal/transport/RF24/driver/RF24.cpp deleted file mode 100644 index f50a37f6..00000000 --- a/lib/MySensors/hal/transport/RF24/driver/RF24.cpp +++ /dev/null @@ -1,577 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* Based on maniacbug's RF24 library, copyright (C) 2011 J. Coliz -* RF24 driver refactored and optimized for speed and size, copyright (C) 2017 Olivier Mauti -*/ - -#include "RF24.h" - -// debug output -#if defined(MY_DEBUG_VERBOSE_RF24) -#define RF24_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< DEBUG -#else -#define RF24_DEBUG(x,...) //!< DEBUG null -#endif - -LOCAL uint8_t RF24_BASE_ID[MY_RF24_ADDR_WIDTH] = { MY_RF24_BASE_RADIO_ID }; -LOCAL uint8_t RF24_NODE_ADDRESS = RF24_BROADCAST_ADDRESS; - -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -LOCAL RF24_receiveCallbackType RF24_receiveCallback = NULL; -#endif - -#if defined(__linux__) -uint8_t RF24_spi_rxbuff[32+1] ; //SPI receive buffer (payload max 32 bytes) -uint8_t RF24_spi_txbuff[32+1] -; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command) -#endif - -LOCAL void RF24_csn(const bool level) -{ -#if defined(__linux__) - (void)level; -#else - hwDigitalWrite(MY_RF24_CS_PIN, level); -#endif -} - -LOCAL void RF24_ce(const bool level) -{ - hwDigitalWrite(MY_RF24_CE_PIN, level); -} - -LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t *buf, uint8_t len, - const bool readMode) -{ - uint8_t status; - uint8_t *current = buf; -#if !defined(MY_SOFTSPI) && defined(SPI_HAS_TRANSACTION) - RF24_SPI.beginTransaction(SPISettings(MY_RF24_SPI_SPEED, RF24_SPI_DATA_ORDER, - RF24_SPI_DATA_MODE)); -#endif - - RF24_csn(LOW); - // timing - delayMicroseconds(10); -#ifdef __linux__ - uint8_t *prx = RF24_spi_rxbuff; - uint8_t *ptx = RF24_spi_txbuff; - uint8_t size = len + 1; // Add register value to transmit buffer - - *ptx++ = cmd; - while ( len-- ) { - if (readMode) { - *ptx++ = RF24_CMD_NOP; - } else { - *ptx++ = *current++; - } - } - RF24_SPI.transfernb( (char *) RF24_spi_txbuff, (char *) RF24_spi_rxbuff, size); - if (readMode) { - if (size == 2) { - status = *++prx; // result is 2nd byte of receive buffer - } else { - status = *prx++; // status is 1st byte of receive buffer - // decrement before to skip status byte - while (--size && (buf != NULL)) { - *buf++ = *prx++; - } - } - } else { - status = *prx; // status is 1st byte of receive buffer - } -#else - status = RF24_SPI.transfer(cmd); - while ( len-- ) { - if (readMode) { - status = RF24_SPI.transfer(RF24_CMD_NOP); - if (buf != NULL) { - *current++ = status; - } - } else { - (void)RF24_SPI.transfer(*current++); - } - } -#endif - - RF24_csn(HIGH); -#if !defined(MY_SOFTSPI) && defined(SPI_HAS_TRANSACTION) - RF24_SPI.endTransaction(); -#endif - // timing - delayMicroseconds(10); - return status; -} - -LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd) -{ - return RF24_spiMultiByteTransfer(cmd, NULL, 0, false); -} - -LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd) -{ - const uint8_t value = RF24_spiMultiByteTransfer(cmd, NULL, 1, true); - RF24_DEBUG(PSTR("RF24:RBR:REG=%" PRIu8 ",VAL=%" PRIu8 "\n"), cmd & RF24_REGISTER_MASK, value); - return value; -} - -LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, uint8_t value) -{ - RF24_DEBUG(PSTR("RF24:WBR:REG=%" PRIu8 ",VAL=%" PRIu8 "\n"), cmd & RF24_REGISTER_MASK, value); - return RF24_spiMultiByteTransfer( cmd, &value, 1, false); -} - -LOCAL void RF24_flushRX(void) -{ - RF24_DEBUG(PSTR("RF24:FRX\n")); - RF24_spiByteTransfer(RF24_CMD_FLUSH_RX); -} - -LOCAL void RF24_flushTX(void) -{ - RF24_DEBUG(PSTR("RF24:FTX\n")); - RF24_spiByteTransfer(RF24_CMD_FLUSH_TX); -} - -LOCAL uint8_t RF24_getStatus(void) -{ - return RF24_spiByteTransfer(RF24_CMD_NOP); -} - -LOCAL uint8_t RF24_getFIFOStatus(void) -{ - return RF24_readByteRegister(RF24_REG_FIFO_STATUS); -} - -LOCAL void RF24_setChannel(const uint8_t channel) -{ - RF24_writeByteRegister(RF24_REG_RF_CH,channel); -} - -LOCAL void RF24_setRetries(const uint8_t retransmitDelay, const uint8_t retransmitCount) -{ - RF24_writeByteRegister(RF24_REG_SETUP_RETR, - retransmitDelay << RF24_ARD | retransmitCount << RF24_ARC); -} - -LOCAL void RF24_setAddressWidth(const uint8_t addressWidth) -{ - RF24_writeByteRegister(RF24_REG_SETUP_AW, addressWidth - 2); -} - -LOCAL void RF24_setRFSetup(const uint8_t RFsetup) -{ - RF24_writeByteRegister(RF24_REG_RF_SETUP, RFsetup); -} - -LOCAL void RF24_setFeature(const uint8_t feature) -{ - RF24_writeByteRegister(RF24_REG_FEATURE, feature); - - if (RF24_getFeature() != feature) { - // toggle features (necessary on some clones and non-P versions) - RF24_enableFeatures(); - RF24_writeByteRegister(RF24_REG_FEATURE, feature); - } -} - -LOCAL uint8_t RF24_getFeature(void) -{ - return RF24_readByteRegister(RF24_REG_FEATURE); -} - -LOCAL void RF24_setPipe(const uint8_t pipe) -{ - RF24_writeByteRegister(RF24_REG_EN_RXADDR, pipe); -} - -LOCAL void RF24_setAutoACK(const uint8_t pipe) -{ - RF24_writeByteRegister(RF24_REG_EN_AA, pipe); -} - -LOCAL void RF24_setDynamicPayload(const uint8_t pipe) -{ - RF24_writeByteRegister(RF24_REG_DYNPD, pipe); -} - -LOCAL void RF24_setRFConfiguration(const uint8_t configuration) -{ - RF24_writeByteRegister(RF24_REG_NRF_CONFIG, configuration); -} - -LOCAL void RF24_setPipeAddress(const uint8_t pipe, uint8_t *address, const uint8_t addressWidth) -{ - RF24_writeMultiByteRegister(pipe, address, addressWidth); -} - -LOCAL void RF24_setPipeLSB(const uint8_t pipe, const uint8_t LSB) -{ - RF24_writeByteRegister(pipe, LSB); -} - -LOCAL uint8_t RF24_getObserveTX(void) -{ - return RF24_readByteRegister(RF24_REG_OBSERVE_TX); -} - -LOCAL uint8_t RF24_setStatus(const uint8_t status) -{ - return RF24_writeByteRegister(RF24_REG_STATUS, status); -} - -LOCAL void RF24_enableFeatures(void) -{ - RF24_RAW_writeByteRegister(RF24_CMD_ACTIVATE, 0x73); -} - -LOCAL void RF24_openWritingPipe(const uint8_t recipient) -{ - RF24_DEBUG(PSTR("RF24:OWP:RCPT=%" PRIu8 "\n"), recipient); // open writing pipe - // only write LSB of RX0 and TX pipe - RF24_setPipeLSB(RF24_REG_RX_ADDR_P0, recipient); - RF24_setPipeLSB(RF24_REG_TX_ADDR, recipient); -} - -LOCAL void RF24_startListening(void) -{ - RF24_DEBUG(PSTR("RF24:STL\n")); // start listening - // toggle PRX - RF24_setRFConfiguration(RF24_CONFIGURATION | _BV(RF24_PWR_UP) | _BV(RF24_PRIM_RX) ); - // all RX pipe addresses must be unique, therefore skip if node ID is RF24_BROADCAST_ADDRESS - if(RF24_NODE_ADDRESS!= RF24_BROADCAST_ADDRESS) { - RF24_setPipeLSB(RF24_REG_RX_ADDR_P0, RF24_NODE_ADDRESS); - } - // start listening - RF24_ce(HIGH); -} - -LOCAL void RF24_stopListening(void) -{ - RF24_DEBUG(PSTR("RF24:SPL\n")); // stop listening - RF24_ce(LOW); - // timing - delayMicroseconds(130); - RF24_setRFConfiguration(RF24_CONFIGURATION | _BV(RF24_PWR_UP) ); - // timing - delayMicroseconds(100); -} - -LOCAL void RF24_powerDown(void) -{ -#if defined(MY_RF24_POWER_PIN) - hwDigitalWrite(MY_RF24_POWER_PIN, LOW); -#endif -} - -LOCAL void RF24_powerUp(void) -{ -#if defined(MY_RF24_POWER_PIN) - hwDigitalWrite(MY_RF24_POWER_PIN, HIGH); - delay(RF24_POWERUP_DELAY_MS); // allow VCC to settle -#endif -} -LOCAL void RF24_sleep(void) -{ - RF24_DEBUG(PSTR("RF24:SLP\n")); // put radio to sleep - RF24_ce(LOW); - RF24_setRFConfiguration(RF24_CONFIGURATION); -} - -LOCAL void RF24_standBy(void) -{ - RF24_DEBUG(PSTR("RF24:SBY\n")); // put radio to standby - RF24_ce(LOW); - RF24_setRFConfiguration(RF24_CONFIGURATION | _BV(RF24_PWR_UP)); - // There must be a delay of up to 4.5ms after the nRF24L01+ leaves power down mode before the CE is set high. - delayMicroseconds(4500); -} - - -LOCAL bool RF24_sendMessage(const uint8_t recipient, const void *buf, const uint8_t len, - const bool noACK) -{ - RF24_stopListening(); - RF24_openWritingPipe(recipient); - RF24_DEBUG(PSTR("RF24:TXM:TO=%" PRIu8 ",LEN=%" PRIu8 "\n"), recipient, len); // send message - // flush TX FIFO - RF24_flushTX(); - if (noACK) { - // noACK messages are only sent once - RF24_setRetries(RF24_SET_ARD, 0); - } - // this command is affected in clones (e.g. Si24R1): flipped NoACK bit when using W_TX_PAYLOAD_NO_ACK / W_TX_PAYLOAD - // AutoACK is disabled on the broadcasting pipe - NO_ACK prevents resending - (void)RF24_spiMultiByteTransfer(RF24_CMD_WRITE_TX_PAYLOAD, (uint8_t *)buf, len, false); - // go, TX starts after ~10us, CE high also enables PA+LNA on supported HW - RF24_ce(HIGH); - // timeout counter to detect HW issues - uint16_t timeout = 0xFFFF; - while (!(RF24_getStatus() & (_BV(RF24_MAX_RT) | _BV(RF24_TX_DS))) && timeout--) { - doYield(); - } - // timeout value after successful TX on 16Mhz AVR ~ 65500, i.e. msg is transmitted after ~36 loop cycles - RF24_ce(LOW); - // reset interrupts - const uint8_t RF24_status = RF24_setStatus(_BV(RF24_RX_DR) | _BV(RF24_TX_DS) | _BV(RF24_MAX_RT)); - // Max retries exceeded - if (RF24_status & _BV(RF24_MAX_RT)) { - // flush packet - RF24_DEBUG(PSTR("?RF24:TXM:MAX_RT\n")); // max retries (normal messages) and noACK messages - RF24_flushTX(); - } - if (noACK) { - RF24_setRetries(RF24_SET_ARD, RF24_SET_ARC); - } - RF24_startListening(); - // true if message sent - return (RF24_status & _BV(RF24_TX_DS) || noACK); -} - -LOCAL uint8_t RF24_getDynamicPayloadSize(void) -{ - uint8_t result = RF24_spiMultiByteTransfer(RF24_CMD_READ_RX_PL_WID, NULL, 1, true); - // check if payload size invalid - if(result > 32) { - RF24_DEBUG(PSTR("!RF24:GDP:PYL INV\n")); // payload len invalid - RF24_flushRX(); - result = 0; - } - return result; -} - -LOCAL bool RF24_isDataAvailable(void) -{ - // prevent debug message flooding -#if defined(MY_DEBUG_VERBOSE_RF24) - const uint8_t value = RF24_spiMultiByteTransfer(RF24_CMD_READ_REGISTER | (RF24_REGISTER_MASK & - (RF24_REG_FIFO_STATUS)), NULL, 1, true); - return (bool)(!(value & _BV(RF24_RX_EMPTY))); -#else - return (bool)(!(RF24_getFIFOStatus() & _BV(RF24_RX_EMPTY)) ); -#endif -} - -LOCAL uint8_t RF24_readMessage(void *buf) -{ - const uint8_t len = RF24_getDynamicPayloadSize(); - RF24_DEBUG(PSTR("RF24:RXM:LEN=%" PRIu8 "\n"), len); // read message - RF24_spiMultiByteTransfer(RF24_CMD_READ_RX_PAYLOAD, (uint8_t *)buf, len, true); - // clear RX interrupt - (void)RF24_setStatus(_BV(RF24_RX_DR)); - return len; -} - -LOCAL void RF24_setNodeAddress(const uint8_t address) -{ - if(address!= RF24_BROADCAST_ADDRESS) { - RF24_NODE_ADDRESS = address; - // enable node pipe - RF24_setPipe(_BV(RF24_ERX_P0 + RF24_BROADCAST_PIPE) | _BV(RF24_ERX_P0)); - // enable autoACK on pipe 0 - RF24_setAutoACK(_BV(RF24_ENAA_P0)); - } -} - -LOCAL uint8_t RF24_getNodeID(void) -{ - return RF24_NODE_ADDRESS; -} - -LOCAL bool RF24_sanityCheck(void) -{ - // detect HW defect, configuration errors or interrupted SPI line, CE disconnect cannot be detected - return (RF24_readByteRegister(RF24_REG_RF_SETUP) == RF24_RF_SETUP) && (RF24_readByteRegister( - RF24_REG_RF_CH) == MY_RF24_CHANNEL); -} -LOCAL int16_t RF24_getTxPowerLevel(void) -{ - // in dBm - return (int16_t)((-6) * (3-((RF24_readByteRegister(RF24_REG_RF_SETUP) >> 1) & 3))); -} - -LOCAL uint8_t RF24_getTxPowerPercent(void) -{ - // report TX level in %, 0 (LOW) = 25%, 3 (MAX) = 100 - const uint8_t result = 25 + (((RF24_readByteRegister(RF24_REG_RF_SETUP) >> 2) & 3) * 25); - return result; -} -LOCAL bool RF24_setTxPowerLevel(const uint8_t newPowerLevel) -{ - const uint8_t registerContent = RF24_readByteRegister(RF24_REG_RF_SETUP); - RF24_writeByteRegister(RF24_REG_RF_SETUP, (registerContent & 0xF9) | ((newPowerLevel & 3) << 1)); - RF24_DEBUG(PSTR("RF24:STX:LEVEL=%" PRIu8 "\n"), newPowerLevel); - return true; -} - -LOCAL bool RF24_setTxPowerPercent(const uint8_t newPowerPercent) -{ - const uint8_t newPowerLevel = static_cast(RF24_MIN_POWER_LEVEL + (RF24_MAX_POWER_LEVEL - - RF24_MIN_POWER_LEVEL) * (newPowerPercent / 100.0f)); - return RF24_setTxPowerLevel(newPowerLevel); -} -LOCAL int16_t RF24_getSendingRSSI(void) -{ - // calculate pseudo-RSSI based on retransmission counter (ARC) - // min -104dBm at 250kBps - // Arbitrary definition: ARC 0 == -29, ARC 15 = -104 - return static_cast(-29 - (8 * (RF24_getObserveTX() & 0xF))); -} - -LOCAL void RF24_enableConstantCarrierWave(void) -{ - RF24_standBy(); - RF24_setRFSetup(RF24_RF_SETUP | _BV(RF24_CONT_WAVE) | _BV(RF24_PLL_LOCK) ); - RF24_ce(HIGH); -} - -LOCAL void RF24_disableConstantCarrierWave(void) -{ - RF24_ce(LOW); - RF24_setRFSetup(RF24_RF_SETUP); -} - -LOCAL bool RF24_getReceivedPowerDetector(void) -{ - // nRF24L01+ only. nRF24L01 contains a carrier detect function (same register & bit) which works - // slightly different and takes at least 128us to become active. - return (RF24_readByteRegister(RF24_REG_RPD) & _BV(RF24_RPD)) != 0; -} - -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -LOCAL void IRQ_HANDLER_ATTR RF24_irqHandler(void) -{ - if (RF24_receiveCallback) { -#if defined(MY_GATEWAY_SERIAL) && !defined(__linux__) - // Will stay for a while (several 100us) in this interrupt handler. Any interrupts from serial - // rx coming in during our stay will not be handled and will cause characters to be lost. - // As a workaround we re-enable interrupts to allow nested processing of other interrupts. - // Our own handler is disconnected to prevent recursive calling of this handler. - detachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN)); - interrupts(); -#endif - // Read FIFO until empty. - // Procedure acc. to datasheet (pg. 63): - // 1.Read payload, 2.Clear RX_DR IRQ, 3.Read FIFO_status, 4.Repeat when more data available. - // Datasheet (ch. 8.5) states, that the nRF de-asserts IRQ after reading STATUS. - -#if defined(__linux__) - // Start checking if RX-FIFO is not empty, as we might end up here from an interrupt - // for a message we've already read. - if (RF24_isDataAvailable()) { - do { - RF24_receiveCallback(); // Must call RF24_readMessage(), which will clear RX_DR IRQ ! - } while (RF24_isDataAvailable()); - } else { - // Occasionally interrupt is triggered but no data is available - clear RX interrupt only - RF24_setStatus(_BV(RF24_RX_DR)); - logNotice("RF24: Recovered from a bad interrupt trigger.\n"); - } -#else - // Start checking if RX-FIFO is not empty, as we might end up here from an interrupt - // for a message we've already read. - while (RF24_isDataAvailable()) { - RF24_receiveCallback(); // Must call RF24_readMessage(), which will clear RX_DR IRQ ! - } -#endif - -#if defined(MY_GATEWAY_SERIAL) && !defined(__linux__) - // Restore our interrupt handler. - noInterrupts(); - attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), RF24_irqHandler, FALLING); -#endif - } else { - // clear RX interrupt - RF24_setStatus(_BV(RF24_RX_DR)); - } -} - -LOCAL void RF24_registerReceiveCallback(RF24_receiveCallbackType cb) -{ - MY_CRITICAL_SECTION { - RF24_receiveCallback = cb; - } -} -#endif - -LOCAL bool RF24_initialize(void) -{ - RF24_DEBUG(PSTR("RF24:INIT:PIN,CE=%" PRIu8 ",CS=%" PRIu8 "\n"), MY_RF24_CE_PIN, MY_RF24_CS_PIN); - // Initialize pins & HW -#if defined(MY_RF24_POWER_PIN) - hwPinMode(MY_RF24_POWER_PIN, OUTPUT); -#endif - RF24_powerUp(); -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - hwPinMode(MY_RF24_IRQ_PIN,INPUT); -#endif - hwPinMode(MY_RF24_CE_PIN, OUTPUT); -#if !defined(__linux__) - hwPinMode(MY_RF24_CS_PIN, OUTPUT); -#endif - RF24_ce(LOW); - RF24_csn(HIGH); - - // Initialize SPI - RF24_SPI.begin(); -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - // assure SPI can be used from interrupt context - // Note: ESP8266 & SoftSPI currently do not support interrupt usage for SPI, - // therefore it is unsafe to use MY_RF24_IRQ_PIN with ESP8266/SoftSPI! - RF24_SPI.usingInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN)); - // attach interrupt - attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), RF24_irqHandler, FALLING); -#endif - // power up and standby - RF24_standBy(); - // set address width - RF24_setAddressWidth(MY_RF24_ADDR_WIDTH); - // auto retransmit delay 1500us, auto retransmit count 15 - RF24_setRetries(RF24_SET_ARD, RF24_SET_ARC); - // set channel - RF24_setChannel(MY_RF24_CHANNEL); - // set data rate and pa level - RF24_setRFSetup(RF24_RF_SETUP); - // enable ACK payload and dynamic payload - RF24_setFeature(RF24_FEATURE); - // sanity check (this function is P/non-P independent) - if (!RF24_sanityCheck()) { - RF24_DEBUG(PSTR("!RF24:INIT:SANCHK FAIL\n")); // sanity check failed, check wiring or replace module - return false; - } - // enable broadcasting pipe - RF24_setPipe(_BV(RF24_ERX_P0 + RF24_BROADCAST_PIPE)); - // disable AA on all pipes, activate when node pipe set - RF24_setAutoACK(0x00); - // enable dynamic payloads on used pipes - RF24_setDynamicPayload(_BV(RF24_DPL_P0 + RF24_BROADCAST_PIPE) | _BV(RF24_DPL_P0)); - // listen to broadcast pipe - RF24_BASE_ID[0] = RF24_BROADCAST_ADDRESS; - RF24_setPipeAddress(RF24_REG_RX_ADDR_P0 + RF24_BROADCAST_PIPE, (uint8_t *)&RF24_BASE_ID, - RF24_BROADCAST_PIPE > 1 ? 1 : MY_RF24_ADDR_WIDTH); - // pipe 0, set full address, later only LSB is updated - RF24_setPipeAddress(RF24_REG_RX_ADDR_P0, (uint8_t *)&RF24_BASE_ID, MY_RF24_ADDR_WIDTH); - RF24_setPipeAddress(RF24_REG_TX_ADDR, (uint8_t *)&RF24_BASE_ID, MY_RF24_ADDR_WIDTH); - // reset FIFO - RF24_flushRX(); - RF24_flushTX(); - // reset interrupts - RF24_setStatus(_BV(RF24_TX_DS) | _BV(RF24_MAX_RT) | _BV(RF24_RX_DR)); - return true; -} diff --git a/lib/MySensors/hal/transport/RF24/driver/RF24.h b/lib/MySensors/hal/transport/RF24/driver/RF24.h deleted file mode 100644 index cdf54192..00000000 --- a/lib/MySensors/hal/transport/RF24/driver/RF24.h +++ /dev/null @@ -1,407 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* Based on maniacbug's RF24 library, copyright (C) 2011 J. Coliz -* RF24 driver refactored and optimized for speed and size, copyright (C) 2017 Olivier Mauti -* -* Definitions for Nordic nRF24L01+ radios: -* https://www.nordicsemi.com/eng/Products/2.4GHz-RF/nRF24L01P -* -*/ - -/** -* @file RF24.h -* -* @defgroup RF24grp RF24 -* @ingroup internals -* @{ -* -* RF24 driver-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE -* - [!] Exclamation mark is prepended in case of error -* -* |E| SYS | SUB | Message | Comment -* |-|------|------|----------------------|--------------------------------------------------------------------- -* | | RF24 | INIT | PIN,CE=%%d,CS=%%d | Initialise RF24 radio, pin configuration: chip enable (CE), chip select (CS) -* |!| RF24 | INIT | SANCHK FAIL | Sanity check failed, check wiring or replace module -* | | RF24 | SPP | PCT=%%d,TX LEVEL=%%d | Set TX level, input TX percent (PCT) -* | | RF24 | RBR | REG=%%d,VAL=%%d | Read register (REG), value=(VAL) -* | | RF24 | WBR | REG=%%d,VAL=%%d | Write register (REG), value=(VAL) -* | | RF24 | FRX | | Flush RX buffer -* | | RF24 | FTX | | Flush TX buffer -* | | RF24 | OWP | RCPT=%%d | Open writing pipe, recipient=(RCPT) -* | | RF24 | STL | | Start listening -* | | RF24 | SPL | | Stop listening -* | | RF24 | SLP | | Set radio to sleep -* | | RF24 | SBY | | Set radio to standby -* | | RF24 | TXM | TO=%%d,LEN=%%d | Transmit message to=(TO), length=(LEN) -* |!| RF24 | TXM | MAX_RT | Max TX retries, no ACK received -* |!| RF24 | GDP | PYL INV | Invalid payload size -* | | RF24 | RXM | LEN=%%d | Read message, length=(LEN) -* | | RF24 | STX | LEVEL=%%d | Set TX level, level=(LEVEL) -* -*/ - -#ifndef __RF24_H__ -#define __RF24_H__ - -#include "RF24registers.h" - -#if !defined(RF24_SPI) -#define RF24_SPI hwSPI //!< default SPI -#endif - -#if defined(ARDUINO_ARCH_AVR) -#define DEFAULT_RF24_CE_PIN (9) //!< DEFAULT_RF24_CE_PIN -#elif defined(ARDUINO_ARCH_ESP8266) -#define DEFAULT_RF24_CE_PIN (4) //!< DEFAULT_RF24_CE_PIN -#elif defined(ARDUINO_ARCH_ESP32) -#define DEFAULT_RF24_CE_PIN (17) //!< DEFAULT_RF24_CE_PIN -#elif defined(ARDUINO_ARCH_SAMD) -#define DEFAULT_RF24_CE_PIN (27) //!< DEFAULT_RF24_CE_PIN -#elif defined(LINUX_ARCH_RASPBERRYPI) -#define DEFAULT_RF24_CE_PIN (22) //!< DEFAULT_RF24_CE_PIN -//#define DEFAULT_RF24_CS_PIN (24) //!< DEFAULT_RF24_CS_PIN -#elif defined(ARDUINO_ARCH_STM32F1) -#define DEFAULT_RF24_CE_PIN (PB0) //!< DEFAULT_RF24_CE_PIN -#elif defined(TEENSYDUINO) -#define DEFAULT_RF24_CE_PIN (9) //!< DEFAULT_RF24_CE_PIN -#else -#define DEFAULT_RF24_CE_PIN (9) //!< DEFAULT_RF24_CE_PIN -#endif - -#define DEFAULT_RF24_CS_PIN (SS) //!< DEFAULT_RF24_CS_PIN - - -#define LOCAL static //!< static - -// SPI settings -#define RF24_SPI_DATA_ORDER MSBFIRST //!< RF24_SPI_DATA_ORDER -#define RF24_SPI_DATA_MODE SPI_MODE0 //!< RF24_SPI_DATA_MODE - -#define RF24_BROADCAST_ADDRESS (255u) //!< RF24_BROADCAST_ADDRESS - -// verify RF24 IRQ defs -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -#if !defined(MY_RF24_IRQ_PIN) -#error Message buffering feature requires MY_RF24_IRQ_PIN to be defined! -#endif -// SoftSPI does not support usingInterrupt() -#ifdef MY_SOFTSPI -#error RF24 IRQ usage cannot be used with Soft SPI -#endif -// ESP8266 does not support usingInterrupt() -#ifdef ARDUINO_ARCH_ESP8266 -#error RF24 IRQ usage cannot be used with ESP8266 -#endif -#ifndef SPI_HAS_TRANSACTION -#error RF24 IRQ usage requires transactional SPI support -#endif -#else -#ifdef MY_RX_MESSAGE_BUFFER_SIZE -#error Receive message buffering requires RF24 IRQ usage -#endif -#endif - - -// RF24 settings -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -#define RF24_CONFIGURATION (uint8_t) ((RF24_CRC_16 << 2) | (1 << RF24_MASK_TX_DS) | (1 << RF24_MASK_MAX_RT)) //!< MY_RF24_CONFIGURATION -#else -#define RF24_CONFIGURATION (uint8_t) (RF24_CRC_16 << 2) //!< RF24_CONFIGURATION -#endif -#define RF24_FEATURE (uint8_t)( _BV(RF24_EN_DPL)) //!< RF24_FEATURE -#define RF24_RF_SETUP (uint8_t)(( ((MY_RF24_DATARATE & 0b10 ) << 4) | ((MY_RF24_DATARATE & 0b01 ) << 3) | (MY_RF24_PA_LEVEL << 1) ) + 1) //!< RF24_RF_SETUP, +1 for Si24R1 and LNA - -// powerup delay -#define RF24_POWERUP_DELAY_MS (100u) //!< Power up delay, allow VCC to settle, transport to become fully operational - -// pipes -#define RF24_BROADCAST_PIPE (1u) //!< RF24_BROADCAST_PIPE -#define RF24_NODE_PIPE (0u) //!< RF24_NODE_PIPE - -// functions -/** -* @brief RF24_csn -* @param level -*/ -LOCAL void RF24_csn(const bool level); -/** -* @brief RF24_ce -* @param level -*/ -LOCAL void RF24_ce(const bool level); -/** -* @brief RF24_spiMultiByteTransfer -* @param cmd -* @param buf -* @param len -* @param readMode -* @return -*/ -LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t *buf, const uint8_t len, - const bool readMode); -/** -* @brief RF24_spiByteTransfer -* @param cmd -* @return -*/ -LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd); -/** -* @brief RF24_RAW_readByteRegister -* @param cmd -* @return -*/ -LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd); -/** -* @brief RF24_RAW_writeByteRegister -* @param cmd -* @param value -* @return -*/ -LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, const uint8_t value); - -// helper macros -#define RF24_readByteRegister(__reg) RF24_RAW_readByteRegister(RF24_CMD_READ_REGISTER | (RF24_REGISTER_MASK & (__reg))) //!< RF24_readByteRegister -#define RF24_writeByteRegister(__reg,__value) RF24_RAW_writeByteRegister(RF24_CMD_WRITE_REGISTER | (RF24_REGISTER_MASK & (__reg)), __value) //!< RF24_writeByteRegister -#define RF24_writeMultiByteRegister(__reg,__buf,__len) RF24_spiMultiByteTransfer(RF24_CMD_WRITE_REGISTER | (RF24_REGISTER_MASK & (__reg)),(uint8_t *)__buf, __len,false) //!< RF24_writeMultiByteRegister - -/** -* @brief RF24_flushRX -*/ -LOCAL void RF24_flushRX(void); -/** -* @brief RF24_flushTX -*/ -LOCAL void RF24_flushTX(void); -/** -* @brief RF24_getStatus -* @return -*/ -LOCAL uint8_t RF24_getStatus(void); -/** -* @brief RF24_getFIFOStatus -* @return -*/ -LOCAL uint8_t RF24_getFIFOStatus(void) __attribute__((unused)); -/** -* @brief RF24_openWritingPipe -* @param recipient -*/ -LOCAL void RF24_openWritingPipe(const uint8_t recipient); -/** -* @brief RF24_startListening -*/ -LOCAL void RF24_startListening(void); -/** -* @brief RF24_stopListening -*/ -LOCAL void RF24_stopListening(void); -/** -* @brief RF24_sleep -*/ -LOCAL void RF24_sleep(void); -/** -* @brief RF24_standBy -*/ -LOCAL void RF24_standBy(void); -/** -* @brief RF24_powerDown -*/ -LOCAL void RF24_powerDown(void); -/** -* @brief RF24_powerUp -*/ -LOCAL void RF24_powerUp(void); -/** -* @brief RF24_sendMessage -* @param recipient -* @param buf -* @param len -* @param noACK set True if no ACK is required -* @return -*/ -LOCAL bool RF24_sendMessage(const uint8_t recipient, const void *buf, const uint8_t len, - const bool noACK = false); -/** -* @brief RF24_getDynamicPayloadSize -* @return -*/ -LOCAL uint8_t RF24_getDynamicPayloadSize(void); -/** -* @brief RF24_isDataAvailable -* @return -*/ -LOCAL bool RF24_isDataAvailable(void); -/** -* @brief RF24_readMessage -* @return -*/ -LOCAL uint8_t RF24_readMessage(void *buf); -/** -* @brief RF24_setNodeAddress -* @param address -*/ -LOCAL void RF24_setNodeAddress(const uint8_t address); -/** -* @brief RF24_getNodeID -* @return -*/ -LOCAL uint8_t RF24_getNodeID(void); -/** -* @brief RF24_sanityCheck -* @return -*/ -LOCAL bool RF24_sanityCheck(void); -/** -* @brief RF24_initialize -* @return -*/ -LOCAL bool RF24_initialize(void); -/** -* @brief RF24_setChannel -* @param channel -*/ -LOCAL void RF24_setChannel(const uint8_t channel); -/** -* @brief RF24_setRetries -* @param retransmitDelay -* @param retransmitCount -*/ -LOCAL void RF24_setRetries(const uint8_t retransmitDelay, const uint8_t retransmitCount); -/** -* @brief RF24_setAddressWidth -* @param addressWidth -*/ -LOCAL void RF24_setAddressWidth(const uint8_t addressWidth); -/** -* @brief RF24_setRFSetup -* @param RFsetup -*/ -LOCAL void RF24_setRFSetup(const uint8_t RFsetup); -/** -* @brief RF24_setFeature -* @param feature -*/ -LOCAL void RF24_setFeature(const uint8_t feature); -/** -* @brief RF24_getFeature -* @return -*/ -LOCAL uint8_t RF24_getFeature(void); -/** -* @brief RF24_setPipe -* @param pipe -*/ -LOCAL void RF24_setPipe(const uint8_t pipe); -/** -* @brief RF24_setAutoACK -* @param pipe -*/ -LOCAL void RF24_setAutoACK(const uint8_t pipe); -/** -* @brief RF24_setDynamicPayload -* @param pipe -*/ -LOCAL void RF24_setDynamicPayload(const uint8_t pipe); -/** -* @brief RF24_setRFConfiguration -* @param configuration -*/ -LOCAL void RF24_setRFConfiguration(const uint8_t configuration); -/** -* @brief RF24_setPipeAddress -* @param pipe -* @param address -* @param addressWidth -*/ -LOCAL void RF24_setPipeAddress(const uint8_t pipe, uint8_t *address, const uint8_t addressWidth); -/** -* @brief RF24_setPipeLSB -* @param pipe -* @param LSB -*/ -LOCAL void RF24_setPipeLSB(const uint8_t pipe, const uint8_t LSB); -/** -* @brief RF24_getObserveTX -* @return -*/ -LOCAL uint8_t RF24_getObserveTX(void); -/** -* @brief RF24_setStatus -* @param status -* @return status byte before setting new status -*/ -LOCAL uint8_t RF24_setStatus(const uint8_t status); -/** -* @brief RF24_enableFeatures -*/ -LOCAL void RF24_enableFeatures(void); -/** -* @brief RF24_getTxPowerPercent -* @return -*/ -LOCAL uint8_t RF24_getTxPowerPercent(void); -/** -* @brief RF24_getTxPowerLevel -* @return -*/ -LOCAL int16_t RF24_getTxPowerLevel(void); -/** -* @brief RF24_setTxPowerPercent -* @param newPowerPercent -* @return -*/ -LOCAL bool RF24_setTxPowerPercent(const uint8_t newPowerPercent); -/** -* @brief RF24_getSendingRSSI -* @return Pseudo-RSSI based on ARC register -*/ -LOCAL int16_t RF24_getSendingRSSI(void); -/** -* @brief Generate a constant carrier wave at active channel & transmit power (for testing only). -*/ -LOCAL void RF24_enableConstantCarrierWave(void) __attribute__((unused)); -/** -* @brief Stop generating a constant carrier wave (for testing only). -*/ -LOCAL void RF24_disableConstantCarrierWave(void) __attribute__((unused)); -/** -* @brief Retrieve latched RPD power level, in receive mode (for testing, nRF24L01+ only). -* @return True when power level >-64dBm for more than 40us. -*/ -LOCAL bool RF24_getReceivedPowerDetector(void) __attribute__((unused)); - -#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -/** -* @brief Callback type -*/ -typedef void (*RF24_receiveCallbackType)(void); -/** -* @brief RF24_registerReceiveCallback -* Register a callback, which will be called (from interrupt context) for every message received. -* @note When a callback is registered, it _must_ retrieve the message from the nRF24 -* by calling RF24_readMessage(). Otherwise the interrupt will not get deasserted -* and message reception will stop. -* @param cb -*/ -LOCAL void RF24_registerReceiveCallback(RF24_receiveCallbackType cb); -#endif - -#endif // __RF24_H__ - -/** @}*/ diff --git a/lib/MySensors/hal/transport/RF24/driver/RF24registers.h b/lib/MySensors/hal/transport/RF24/driver/RF24registers.h deleted file mode 100644 index 0691f4ed..00000000 --- a/lib/MySensors/hal/transport/RF24/driver/RF24registers.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -* The MySensors Arduino library handles the wireless radio link and protocol -* between your home built sensors/actuators and HA controller of choice. -* The sensors forms a self healing radio network with optional repeaters. Each -* repeater and gateway builds a routing tables in EEPROM which keeps track of the -* network topology allowing messages to be routed to nodes. -* -* Created by Henrik Ekblad -* Copyright (C) 2013-2019 Sensnology AB -* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors -* -* Documentation: http://www.mysensors.org -* Support Forum: http://forum.mysensors.org -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* version 2 as published by the Free Software Foundation. -* -* Based on maniacbug's RF24 library, copyright (C) 2011 J. Coliz -* RF24 driver refactored and optimized for speed and size, copyright (C) 2016 Olivier Mauti -*/ - -// PA levels -#define RF24_PA_MIN (0) -#define RF24_PA_LOW (1) -#define RF24_PA_HIGH (2) -#define RF24_PA_MAX (3) - -// power level limits -#define RF24_MIN_POWER_LEVEL (0) -#define RF24_MAX_POWER_LEVEL (3) - -// data rate -#define RF24_1MBPS (0) -#define RF24_2MBPS (1) -#define RF24_250KBPS (2) - -// CRC -#define RF24_CRC_DISABLED (0) -#define RF24_CRC_8 (2) -#define RF24_CRC_16 (3) - -// ARD, auto retry delay -#define RF24_SET_ARD (5) //=1500us - -// ARD, auto retry count -#define RF24_SET_ARC (15) - -// nRF24L01(+) register definitions -#define RF24_REG_NRF_CONFIG (0x00) -#define RF24_REG_EN_AA (0x01) -#define RF24_REG_EN_RXADDR (0x02) -#define RF24_REG_SETUP_AW (0x03) -#define RF24_REG_SETUP_RETR (0x04) -#define RF24_REG_RF_CH (0x05) -#define RF24_REG_RF_SETUP (0x06) -#define RF24_REG_STATUS (0x07) -#define RF24_REG_OBSERVE_TX (0x08) -#define RF24_REG_RPD (0x09) // nRF24L01+ -#define RF24_REG_CD (RF24_REG_RPD) // nRF24L01 -#define RF24_REG_RX_ADDR_P0 (0x0A) -#define RF24_REG_RX_ADDR_P1 (0x0B) -#define RF24_REG_RX_ADDR_P2 (0x0C) -#define RF24_REG_RX_ADDR_P3 (0x0D) -#define RF24_REG_RX_ADDR_P4 (0x0E) -#define RF24_REG_RX_ADDR_P5 (0x0F) -#define RF24_REG_TX_ADDR (0x10) -#define RF24_REG_RX_PW_P0 (0x11) -#define RF24_REG_RX_PW_P1 (0x12) -#define RF24_REG_RX_PW_P2 (0x13) -#define RF24_REG_RX_PW_P3 (0x14) -#define RF24_REG_RX_PW_P4 (0x15) -#define RF24_REG_RX_PW_P5 (0x16) -#define RF24_REG_FIFO_STATUS (0x17) -#define RF24_REG_DYNPD (0x1C) -#define RF24_REG_FEATURE (0x1D) - -// mask -#define RF24_REGISTER_MASK (0x1F) - -// instructions -#define RF24_CMD_READ_REGISTER (0x00) -#define RF24_CMD_WRITE_REGISTER (0x20) -#define RF24_CMD_ACTIVATE (0x50) -#define RF24_CMD_READ_RX_PL_WID (0x60) -#define RF24_CMD_READ_RX_PAYLOAD (0x61) -#define RF24_CMD_WRITE_TX_PAYLOAD (0xA0) -#define RF24_CMD_WRITE_ACK_PAYLOAD (0xA8) -#define RF24_CMD_WRITE_TX_PAYLOAD_NO_ACK (0xB0) -#define RF24_CMD_FLUSH_TX (0xE1) -#define RF24_CMD_FLUSH_RX (0xE2) -#define RF24_CMD_REUSE_TX_PL (0xE3) -#define RF24_CMD_NOP (0xFF) - -// bit mnemonics -#define RF24_MASK_RX_DR (6) -#define RF24_MASK_TX_DS (5) -#define RF24_MASK_MAX_RT (4) -#define RF24_EN_CRC (3) -#define RF24_CRCO (2) -#define RF24_PWR_UP (1) -#define RF24_PRIM_RX (0) - -// auto ACK -#define RF24_ENAA_P5 (5) -#define RF24_ENAA_P4 (4) -#define RF24_ENAA_P3 (3) -#define RF24_ENAA_P2 (2) -#define RF24_ENAA_P1 (1) -#define RF24_ENAA_P0 (0) - -// rx pipe -#define RF24_ERX_P5 (5) -#define RF24_ERX_P4 (4) -#define RF24_ERX_P3 (3) -#define RF24_ERX_P2 (2) -#define RF24_ERX_P1 (1) -#define RF24_ERX_P0 (0) - -// dynamic payload -#define RF24_DPL_P5 (5) -#define RF24_DPL_P4 (4) -#define RF24_DPL_P3 (3) -#define RF24_DPL_P2 (2) -#define RF24_DPL_P1 (1) -#define RF24_DPL_P0 (0) - -#define RF24_AW (0) -#define RF24_ARD (4) -#define RF24_ARC (0) -#define RF24_PLL_LOCK (4) -#define RF24_CONT_WAVE (7) -#define RF24_RF_DR (3) -#define RF24_RF_PWR (6) -#define RF24_RX_DR (6) -#define RF24_TX_DS (5) -#define RF24_MAX_RT (4) -#define RF24_RX_P_NO (1) -#define RF24_TX_FULL (0) -#define RF24_PLOS_CNT (4) -#define RF24_ARC_CNT (0) -#define RF24_TX_REUSE (6) -#define RF24_FIFO_FULL (5) -#define RF24_TX_EMPTY (4) -#define RF24_RX_FULL (1) -#define RF24_RX_EMPTY (0) -#define RF24_RPD (0) // nRF24L01+ -#define RF24_CD (RF24_RPD) // nRF24L01 - -// features -#define RF24_EN_DPL (2) -#define RF24_EN_ACK_PAY (1) -#define RF24_EN_DYN_ACK (0) - -#define RF24_LNA_HCURR (0) -#define RF24_RF_DR_LOW (5) -#define RF24_RF_DR_HIGH (3) -#define RF24_RF_PWR_LOW (1) -#define RF24_RF_PWR_HIGH (2) diff --git a/lib/MySensors/hal/transport/RFM69/MyTransportRFM69.cpp b/lib/MySensors/hal/transport/RFM69/MyTransportRFM69.cpp deleted file mode 100644 index 6ec2e5db..00000000 --- a/lib/MySensors/hal/transport/RFM69/MyTransportRFM69.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#if defined(MY_RFM69_NEW_DRIVER) - -#include "hal/transport/RFM69/driver/new/RFM69_new.h" - -bool transportInit(void) -{ - const bool result = RFM69_initialise(MY_RFM69_FREQUENCY); -#if defined(MY_GATEWAY_FEATURE) || defined(MY_RFM69_ATC_MODE_DISABLED) - // ATC mode function not used - (void)RFM69_ATCmode; -#else - RFM69_ATCmode(true, MY_RFM69_ATC_TARGET_RSSI_DBM); -#endif - -#ifdef MY_RFM69_ENABLE_ENCRYPTION - uint8_t RFM69_psk[16]; -#ifdef MY_ENCRYPTION_SIMPLE_PASSWD - (void)memset(RFM69_psk, 0, 16); - (void)memcpy(RFM69_psk, MY_ENCRYPTION_SIMPLE_PASSWD, strnlen(MY_ENCRYPTION_SIMPLE_PASSWD, 16)); -#else - hwReadConfigBlock((void *)RFM69_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); -#endif - RFM69_encrypt((const char *)RFM69_psk); - (void)memset(RFM69_psk, 0, 16); // Make sure it is purged from memory when set -#else - (void)RFM69_encrypt; -#endif - return result; -} - -void transportSetAddress(const uint8_t address) -{ - RFM69_setAddress(address); -} - -uint8_t transportGetAddress(void) -{ - return RFM69_getAddress(); -} - -bool transportSend(const uint8_t to, const void *data, uint8_t len, const bool noACK) -{ - return RFM69_sendWithRetry(to, data, len, noACK); -} - -bool transportDataAvailable(void) -{ - RFM69_handler(); - return RFM69_available(); -} - -bool transportSanityCheck(void) -{ - return RFM69_sanityCheck(); -} - -uint8_t transportReceive(void *data) -{ - return RFM69_receive((uint8_t *)data, MAX_MESSAGE_SIZE); -} - -void transportEncrypt(const char *key) -{ - RFM69_encrypt(key); -} - -void transportSleep(void) -{ - (void)RFM69_sleep(); -} - -void transportStandBy(void) -{ - (void)RFM69_standBy(); -} - -void transportPowerDown(void) -{ - (void)RFM69_powerDown(); -} - -void transportPowerUp(void) -{ - (void)RFM69_powerUp(); -} - -bool transportSetTxPowerLevel(const uint8_t powerLevel) -{ - // range 0..23 - return RFM69_setTxPowerLevel(powerLevel); -} - -void transportSetTargetRSSI(const int16_t targetSignalStrength) -{ -#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM69_ATC_MODE_DISABLED) - RFM69_ATCmode(true, targetSignalStrength); -#else - (void)targetSignalStrength; -#endif -} - -int16_t transportGetSendingRSSI(void) -{ - return RFM69_getSendingRSSI(); -} - -int16_t transportGetReceivingRSSI(void) -{ - return RFM69_getReceivingRSSI(); -} - -int16_t transportGetSendingSNR(void) -{ - return INVALID_SNR; -} - -int16_t transportGetReceivingSNR(void) -{ - return INVALID_SNR; -} - -int16_t transportGetTxPowerPercent(void) -{ - return RFM69_getTxPowerPercent(); -} - -int16_t transportGetTxPowerLevel(void) -{ - return RFM69_getTxPowerLevel(); -} - -bool transportSetTxPowerPercent(const uint8_t powerPercent) -{ - return RFM69_setTxPowerPercent(powerPercent); -} - -#else - -#include "hal/transport/RFM69/driver/old/RFM69_old.h" - -RFM69 _radio(MY_RFM69_CS_PIN, MY_RFM69_IRQ_PIN, MY_RFM69HW, MY_RFM69_IRQ_NUM); -uint8_t _address; - -bool transportInit(void) -{ -#if defined(MY_RFM69_POWER_PIN) - //hwPinMode(MY_RFM69_POWER_PIN, OUTPUT); -#endif -#ifdef MY_RF69_DIO5 - //hwPinMode(MY_RF69_DIO5, INPUT); -#endif - // Start up the radio library (_address will be set later by the MySensors library) - if (_radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID)) { -#ifdef MY_RFM69_ENABLE_ENCRYPTION - uint8_t RFM69_psk[16]; -#ifdef MY_ENCRYPTION_SIMPLE_PASSWD - (void)memset(RFM69_psk, 0, 16); - (void)memcpy(RFM69_psk, MY_ENCRYPTION_SIMPLE_PASSWD, strnlen(MY_ENCRYPTION_SIMPLE_PASSWD, 16)); -#else - hwReadConfigBlock((void *)RFM69_psk, (void *)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); -#endif - _radio.encrypt((const char *)RFM69_psk); - (void)memset(RFM69_psk, 0, 16); // Make sure it is purged from memory when set -#endif - return true; - } - return false; -} - -void transportEncrypt(const char *key) -{ - _radio.encrypt(key); -} - -void transportSetAddress(const uint8_t address) -{ - _address = address; - _radio.setAddress(address); -} - -uint8_t transportGetAddress(void) -{ - return _address; -} - -bool transportSend(const uint8_t to, const void *data, const uint8_t len, const bool noACK) -{ - if (noACK) { - (void)_radio.sendWithRetry(to, data, len, 0, 0); - return true; - } - return _radio.sendWithRetry(to, data, len); -} - -bool transportDataAvailable(void) -{ - return _radio.receiveDone(); -} - -bool transportSanityCheck(void) -{ - return _radio.sanityCheck(); -} - -uint8_t transportReceive(void *data) -{ - // save payload length - const uint8_t dataLen = _radio.DATALEN < MAX_MESSAGE_SIZE ? _radio.DATALEN : MAX_MESSAGE_SIZE; - (void)memcpy((void *)data, (void *)_radio.DATA, dataLen); - // Send ack back if this message wasn't a broadcast - if (_radio.ACKRequested()) { - _radio.sendACK(); - } - return dataLen; -} - -void transportSleep(void) -{ - _radio.sleep(); -} - -void transportStandBy(void) -{ - _radio.standBy(); -} - -void transportPowerDown(void) -{ - _radio.powerDown(); -} - -void transportPowerUp(void) -{ - _radio.powerUp(); -} - -int16_t transportGetSendingRSSI(void) -{ - return INVALID_RSSI; -} - -int16_t transportGetReceivingRSSI(void) -{ - return _radio.RSSI; -} - -int16_t transportGetSendingSNR(void) -{ - return INVALID_SNR; -} - -int16_t transportGetReceivingSNR(void) -{ - return INVALID_SNR; -} - -int16_t transportGetTxPowerPercent(void) -{ - return INVALID_PERCENT; -} - -int16_t transportGetTxPowerLevel(void) -{ - return INVALID_LEVEL; -} - -bool transportSetTxPowerLevel(const uint8_t powerLevel) -{ - // not implemented - (void)powerLevel; - return false; -} - -bool transportSetTxPowerPercent(const uint8_t powerPercent) -{ - // not implemented - (void)powerPercent; - return false; -} - - -#endif diff --git a/lib/MySensors/hal/transport/RFM69/driver/new/RFM69_new.cpp b/lib/MySensors/hal/transport/RFM69/driver/new/RFM69_new.cpp deleted file mode 100644 index cf4f0f02..00000000 --- a/lib/MySensors/hal/transport/RFM69/driver/new/RFM69_new.cpp +++ /dev/null @@ -1,1037 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * RFM69 driver refactored for MySensors - * - * Based on : - * - LowPowerLab RFM69 Lib Copyright Felix Rusu (2014), felix@lowpowerlab.com - * - Automatic Transmit Power Control class derived from RFM69 library. - * Discussion and details in this forum post: https://lowpowerlab.com/forum/index.php/topic,688.0.html - * Copyright Thomas Studwell (2014,2015) - * - MySensors generic radio driver implementation Copyright (C) 2017, 2018 Olivier Mauti - * - * Changes by : @tekka, @scalz, @marceloagno - * - * Definitions for Semtech SX1231/H radios: - * https://www.semtech.com/uploads/documents/sx1231.pdf - * https://www.semtech.com/uploads/documents/sx1231h.pdf - */ - -#include "RFM69_new.h" - -// debug -#if defined(MY_DEBUG_VERBOSE_RFM69) -#define RFM69_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< Debug print -#else -#define RFM69_DEBUG(x,...) //!< DEBUG null -#endif - -rfm69_internal_t RFM69; //!< internal variables -volatile uint8_t RFM69_irq; //!< rfm69 irq flag - -#if defined(__linux__) -// SPI RX and TX buffers (max packet len + 1 byte for the command) -uint8_t RFM69_spi_rxbuff[RFM69_MAX_PACKET_LEN + 1]; -uint8_t RFM69_spi_txbuff[RFM69_MAX_PACKET_LEN + 1]; -#endif - -LOCAL void RFM69_csn(const bool level) -{ -#if defined(__linux__) - (void)level; -#else - hwDigitalWrite(MY_RFM69_CS_PIN, level); -#endif -} - -LOCAL void RFM69_prepareSPITransaction(void) -{ -#if !defined(MY_SOFTSPI) && defined(SPI_HAS_TRANSACTION) - RFM69_SPI.beginTransaction(SPISettings(MY_RFM69_SPI_SPEED, RFM69_SPI_DATA_ORDER, - RFM69_SPI_DATA_MODE)); -#endif -} - -LOCAL void RFM69_concludeSPITransaction(void) -{ -#if !defined(MY_SOFTSPI) && defined(SPI_HAS_TRANSACTION) - RFM69_SPI.endTransaction(); -#endif -} - -LOCAL uint8_t RFM69_spiMultiByteTransfer(const uint8_t cmd, uint8_t *buf, uint8_t len, - const bool aReadMode) -{ - uint8_t status; - uint8_t *current = buf; - - RFM69_prepareSPITransaction(); - RFM69_csn(LOW); - -#if defined(__linux__) - uint8_t *prx = RFM69_spi_rxbuff; - uint8_t *ptx = RFM69_spi_txbuff; - uint8_t size = len + 1; // Add register value to transmit buffer - - *ptx++ = cmd; - while (len--) { - if (aReadMode) { - *ptx++ = (uint8_t)RFM69_NOP; - } else { - *ptx++ = *current++; - } - } - RFM69_SPI.transfernb((char *)RFM69_spi_txbuff, (char *)RFM69_spi_rxbuff, size); - if (aReadMode) { - if (size == 2) { - status = *++prx; // result is 2nd byte of receive buffer - } else { - status = *prx++; // status is 1st byte of receive buffer - // decrement before to skip status byte - while (--size && (buf != NULL)) { - *buf++ = *prx++; - } - } - } else { - status = *prx; // status is 1st byte of receive buffer - } -#else - status = RFM69_SPI.transfer(cmd); - while (len--) { - if (aReadMode) { - status = RFM69_SPI.transfer((uint8_t)RFM69_NOP); - if (buf != NULL) { - *current++ = status; - } - } else { - status = RFM69_SPI.transfer(*current++); - } - } -#endif - RFM69_csn(HIGH); - RFM69_concludeSPITransaction(); - return status; -} - -// low level register access -LOCAL inline uint8_t RFM69_RAW_readByteRegister(const uint8_t address) -{ - return RFM69_spiMultiByteTransfer(address, NULL, 1, true); -} - -LOCAL inline uint8_t RFM69_RAW_writeByteRegister(const uint8_t address, uint8_t value) -{ - return RFM69_spiMultiByteTransfer(address, &value, 1, false); -} - -// helper functions -LOCAL inline uint8_t RFM69_readReg(const uint8_t reg) -{ - return RFM69_RAW_readByteRegister(reg & RFM69_READ_REGISTER); -} - -LOCAL inline uint8_t RFM69_writeReg(const uint8_t reg, const uint8_t value) -{ - return RFM69_RAW_writeByteRegister(reg | RFM69_WRITE_REGISTER, value); -} - -LOCAL inline uint8_t RFM69_burstReadReg(const uint8_t reg, void *buf, uint8_t len) -{ - return RFM69_spiMultiByteTransfer(reg & RFM69_READ_REGISTER, (uint8_t *)buf, len, true); -} - -LOCAL inline uint8_t RFM69_burstWriteReg(const uint8_t reg, const void *buf, uint8_t len) -{ - return RFM69_spiMultiByteTransfer(reg | RFM69_WRITE_REGISTER, (uint8_t *)buf, len, false); -} - -LOCAL inline rfm69_RSSI_t RFM69_RSSItoInternal(const int16_t externalRSSI) -{ - return (rfm69_RSSI_t)-(externalRSSI * 2); -} - -LOCAL inline int16_t RFM69_internalToRSSI(const rfm69_RSSI_t internalRSSI) -{ - return (int16_t)-(internalRSSI / 2); -} - -LOCAL bool RFM69_initialise(const uint32_t frequencyHz) -{ - RFM69_DEBUG(PSTR("RFM69:INIT\n")); - // power up radio if power pin defined -#if defined(MY_RFM69_POWER_PIN) - hwPinMode(MY_RFM69_POWER_PIN, OUTPUT); -#endif - RFM69_powerUp(); - // reset radio module if rst pin defined -#if defined(MY_RFM69_RST_PIN) - hwPinMode(MY_RFM69_RST_PIN, OUTPUT); - hwDigitalWrite(MY_RFM69_RST_PIN, HIGH); - // 100uS - delayMicroseconds(100); - hwDigitalWrite(MY_RFM69_RST_PIN, LOW); - // wait until chip ready - delay(5); - RFM69_DEBUG(PSTR("RFM69:INIT:PIN,CS=%" PRIu8 ",IQP=%" PRIu8 ",IQN=%" PRIu8 ",RST=%" PRIu8 "\n"), - MY_RFM69_CS_PIN,MY_RFM69_IRQ_PIN, - MY_RFM69_IRQ_NUM,MY_RFM69_RST_PIN); -#else - RFM69_DEBUG(PSTR("RFM69:INIT:PIN,CS=%" PRIu8 ",IQP=%" PRIu8 ",IQN=%" PRIu8 "\n"),MY_RFM69_CS_PIN, - MY_RFM69_IRQ_PIN, - MY_RFM69_IRQ_NUM); -#endif - - // set variables - RFM69.address = RFM69_BROADCAST_ADDRESS; - RFM69.dataReceived = false; - RFM69.ackReceived = false; - RFM69.txSequenceNumber = 0; // initialise TX sequence counter - RFM69.powerLevel = MY_RFM69_TX_POWER_DBM + 1; // will be overwritten when set - RFM69.radioMode = RFM69_RADIO_MODE_SLEEP; - RFM69.ATCenabled = false; - RFM69.ATCtargetRSSI = RFM69_RSSItoInternal(MY_RFM69_ATC_TARGET_RSSI_DBM); - - // SPI init -#if !defined(__linux__) - hwDigitalWrite(MY_RFM69_CS_PIN, HIGH); - hwPinMode(MY_RFM69_CS_PIN, OUTPUT); -#endif - RFM69_SPI.begin(); - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY); - // set configuration, encryption is disabled - RFM69_setConfiguration(); - RFM69_setFrequency(frequencyHz); - (void)RFM69_setTxPowerLevel(MY_RFM69_TX_POWER_DBM); - -#if defined(MY_DEBUG_VERBOSE_RFM69_REGISTERS) - RFM69_readAllRegs(); -#else - (void)RFM69_readAllRegs; -#endif - //RFM69_DEBUG(PSTR("RFM69:INIT:HWV=%" PRIu8 "\n"),RFM69_readReg(RFM69_REG_VERSION)); - - if (!RFM69_sanityCheck()) { - // sanity check failed, check wiring or replace module - RFM69_DEBUG(PSTR("!RFM69:INIT:SANCHK FAIL\n")); - return false; - } - // IRQ - RFM69_irq = false; - hwPinMode(MY_RFM69_IRQ_PIN, INPUT); - attachInterrupt(MY_RFM69_IRQ_NUM, RFM69_interruptHandler, RISING); - return true; -} - -LOCAL void RFM69_clearFIFO(void) -{ - (void)RFM69_writeReg(RFM69_REG_IRQFLAGS2, RFM69_IRQFLAGS2_FIFOOVERRUN); -} -// IRQ handler: PayloadReady (RX) & PacketSent (TX) mapped to DI0 -LOCAL void IRQ_HANDLER_ATTR RFM69_interruptHandler(void) -{ - // set flag - RFM69_irq = true; -} - -LOCAL void RFM69_interruptHandling(void) -{ - const uint8_t regIrqFlags2 = RFM69_readReg(RFM69_REG_IRQFLAGS2); - if (RFM69.radioMode == RFM69_RADIO_MODE_RX && (regIrqFlags2 & RFM69_IRQFLAGS2_PAYLOADREADY)) { - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY); - // use the fifo level irq as indicator if header bytes received - if (regIrqFlags2 & RFM69_IRQFLAGS2_FIFOLEVEL) { - RFM69_prepareSPITransaction(); - RFM69_csn(LOW); -#if defined(__linux__) - char data[RFM69_MAX_PACKET_LEN + 1]; // max packet len + 1 byte for the command - data[0] = RFM69_REG_FIFO & RFM69_READ_REGISTER; - RFM69_SPI.transfern(data, 3); - - RFM69.currentPacket.header.packetLen = data[1]; - RFM69.currentPacket.header.recipient = data[2]; - - if (RFM69.currentPacket.header.packetLen > RFM69_MAX_PACKET_LEN) { - RFM69.currentPacket.header.packetLen = RFM69_MAX_PACKET_LEN; - } - - data[0] = RFM69_REG_FIFO & RFM69_READ_REGISTER; - //SPI.transfern(data, RFM69.currentPacket.header.packetLen - 1); //TODO: Wrong packetLen? - RFM69_SPI.transfern(data, RFM69.currentPacket.header.packetLen); - - //(void)memcpy((void *)&RFM69.currentPacket.data[2], (void *)&data[1], RFM69.currentPacket.header.packetLen - 2); //TODO: Wrong packetLen? - (void)memcpy((void *)&RFM69.currentPacket.data[2], (void *)&data[1], - RFM69.currentPacket.header.packetLen - 1); - - if (RFM69.currentPacket.header.version >= RFM69_MIN_PACKET_HEADER_VERSION) { - RFM69.currentPacket.payloadLen = min(RFM69.currentPacket.header.packetLen - (RFM69_HEADER_LEN - 1), - RFM69_MAX_PACKET_LEN); - RFM69.ackReceived = RFM69_getACKReceived(RFM69.currentPacket.header.controlFlags); - RFM69.dataReceived = !RFM69.ackReceived; - } -#else - (void)RFM69_SPI.transfer(RFM69_REG_FIFO & RFM69_READ_REGISTER); - // set reading pointer - uint8_t *current = (uint8_t *)&RFM69.currentPacket; - bool headerRead = false; - // first read header - uint8_t readingLength = RFM69_HEADER_LEN; - while (readingLength--) { - *current++ = RFM69_SPI.transfer((uint8_t)RFM69_NOP); - if (!readingLength && !headerRead) { - // header read - headerRead = true; - if (RFM69.currentPacket.header.version >= RFM69_MIN_PACKET_HEADER_VERSION) { - // read payload - readingLength = min(RFM69.currentPacket.header.packetLen - (RFM69_HEADER_LEN - 1), - RFM69_MAX_PACKET_LEN); - // save payload length - RFM69.currentPacket.payloadLen = readingLength; - RFM69.ackReceived = RFM69_getACKReceived(RFM69.currentPacket.header.controlFlags); - RFM69.dataReceived = !RFM69.ackReceived; - } - } - } -#endif - RFM69_csn(HIGH); - RFM69_concludeSPITransaction(); - } - RFM69.currentPacket.RSSI = RFM69_readRSSI(); - // radio remains in stdby until packet read - } else { - // back to RX - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_RX); - } -} - -LOCAL void RFM69_handler(void) -{ - if (RFM69_irq) { - // radio is in STDBY - // clear flag, 8bit - no need for critical section - RFM69_irq = false; - RFM69_interruptHandling(); - } -} - -LOCAL bool RFM69_available(void) -{ - if (RFM69.dataReceived) { - // data received - we are still in STDBY - return true; - } else if (RFM69.radioMode == RFM69_RADIO_MODE_TX) { - // still in TX - return false; - } else if (RFM69.radioMode != RFM69_RADIO_MODE_RX) { // adding this check speeds up loop() :) - // no data received and not in RX - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_RX); - } - return false; -} - -LOCAL uint8_t RFM69_receive(uint8_t *buf, const uint8_t maxBufSize) -{ - const uint8_t payloadLen = min(RFM69.currentPacket.payloadLen, maxBufSize); - const uint8_t sender = RFM69.currentPacket.header.sender; - const rfm69_sequenceNumber_t sequenceNumber = RFM69.currentPacket.header.sequenceNumber; - const uint8_t controlFlags = RFM69.currentPacket.header.controlFlags; - const rfm69_RSSI_t RSSI = RFM69.currentPacket.RSSI; - - if (buf != NULL) { - (void)memcpy((void *)buf, (void *)&RFM69.currentPacket.payload, payloadLen); - } - // clear data flag - RFM69.dataReceived = false; - if (RFM69_getACKRequested(controlFlags) && !RFM69_getACKReceived(controlFlags)) { -#if defined(MY_GATEWAY_FEATURE) && (F_CPU>16*1000000ul) - // delay for fast GW and slow nodes - delay(50); -#endif - RFM69_sendACK(sender, sequenceNumber, RSSI); - } - return payloadLen; -} - -LOCAL bool RFM69_channelFree(void) -{ - // returns true if channel activity under RFM69_CSMA_LIMIT_DBM - const rfm69_RSSI_t RSSI = RFM69_readRSSI(false); - RFM69_DEBUG(PSTR("RFM69:CSMA:RSSI=%" PRIi16 "\n"), RFM69_internalToRSSI(RSSI)); - return (RSSI > RFM69_RSSItoInternal(MY_RFM69_CSMA_LIMIT_DBM)); -} - -LOCAL bool RFM69_sendFrame(rfm69_packet_t *packet, const bool increaseSequenceCounter) -{ - // ensure we are in RX for correct RSSI sampling, dirty hack to enforce rx restart :) - RFM69.radioMode = RFM69_RADIO_MODE_STDBY; - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_RX); - delay(1); // timing for correct RSSI sampling - const uint32_t CSMA_START_MS = hwMillis(); - while (!RFM69_channelFree() && - ((hwMillis() - CSMA_START_MS) < MY_RFM69_CSMA_TIMEOUT_MS)) { - doYield(); - } - // set radio to standby to load fifo - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY); - if (increaseSequenceCounter) { - // increase sequence counter, overflow is ok - RFM69.txSequenceNumber++; - } - // clear FIFO and flags - RFM69_clearFIFO(); - // assign sequence number - packet->header.sequenceNumber = RFM69.txSequenceNumber; - - // write packet - const uint8_t finalLen = packet->payloadLen + RFM69_HEADER_LEN; // including length byte - (void)RFM69_burstWriteReg(RFM69_REG_FIFO, packet->data, finalLen); - - // send message - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_TX); // irq upon txsent - const uint32_t txStartMS = hwMillis(); - while (!RFM69_irq && (hwMillis() - txStartMS < MY_RFM69_TX_TIMEOUT_MS)) { - doYield(); - }; - return RFM69_irq; -} - -LOCAL bool RFM69_send(const uint8_t recipient, uint8_t *data, const uint8_t len, - const rfm69_controlFlags_t flags, const bool increaseSequenceCounter) -{ - // assemble packet - rfm69_packet_t packet; - packet.header.version = RFM69_PACKET_HEADER_VERSION; - packet.header.sender = RFM69.address; - packet.header.recipient = recipient; - packet.payloadLen = min(len, (uint8_t)RFM69_MAX_PAYLOAD_LEN); - packet.header.controlFlags = flags; - (void)memcpy((void *)&packet.payload, (void *)data, packet.payloadLen); // copy payload - packet.header.packetLen = packet.payloadLen + (RFM69_HEADER_LEN - 1); // -1 length byte - return RFM69_sendFrame(&packet, increaseSequenceCounter); -} - -LOCAL void RFM69_setFrequency(const uint32_t frequencyHz) -{ - const uint32_t freqHz = (uint32_t)(frequencyHz / RFM69_FSTEP); - RFM69_writeReg(RFM69_REG_FRFMSB, (uint8_t)((freqHz >> 16) & 0xFF)); - RFM69_writeReg(RFM69_REG_FRFMID, (uint8_t)((freqHz >> 8) & 0xFF)); - RFM69_writeReg(RFM69_REG_FRFLSB, (uint8_t)(freqHz & 0xFF)); -} - -LOCAL void RFM69_setHighPowerRegs(const bool onOff) -{ -#if defined(RFM69_VERSION_HW) - RFM69_writeReg(RFM69_REG_OCP, (onOff ? RFM69_OCP_OFF : RFM69_OCP_ON ) | RFM69_OCP_TRIM_95); - RFM69_writeReg(RFM69_REG_TESTPA1, onOff ? 0x5D : 0x55); - RFM69_writeReg(RFM69_REG_TESTPA2, onOff ? 0x7C : 0x70); -#else - (void)onOff; -#endif -} - -LOCAL bool RFM69_setTxPowerLevel(rfm69_powerlevel_t newPowerLevel) -{ - // limit power levels - newPowerLevel = max((rfm69_powerlevel_t)RFM69_MIN_POWER_LEVEL_DBM, newPowerLevel); - newPowerLevel = min((rfm69_powerlevel_t)RFM69_MAX_POWER_LEVEL_DBM, newPowerLevel); - - if (RFM69.powerLevel == newPowerLevel) { - RFM69_DEBUG(PSTR("RFM69:PTX:NO ADJ\n")); - return false; - } - - RFM69.powerLevel = newPowerLevel; - uint8_t palevel; -#if !defined(RFM69_VERSION_HW) - // -18dBm to +13dBm, PA0, offset 0, i.e. -18dBm = level 0 - palevel = RFM69_PALEVEL_PA0_ON | ((uint8_t)(newPowerLevel + 18)); - -#else - if (newPowerLevel <= (rfm69_powerlevel_t)13) { - // -2dBm to +13dBm, PA1, offset 16, i.e. -2dBm = level 16 - palevel = RFM69_PALEVEL_PA1_ON | ((uint8_t)(newPowerLevel + 18)); - } else if (newPowerLevel >= (rfm69_powerlevel_t)RFM69_HIGH_POWER_DBM) { - // +18dBm to +20dBm, PA1 and PA2, Boost settings, 18dBm = level 29 - palevel = RFM69_PALEVEL_PA1_ON | RFM69_PALEVEL_PA2_ON | ((uint8_t)(newPowerLevel + 11)); - } else { - // +14dBm to +17dBm, PA1 and PA2 - palevel = RFM69_PALEVEL_PA1_ON | RFM69_PALEVEL_PA2_ON | ((uint8_t)(newPowerLevel + 14)); - } -#endif - RFM69_writeReg(RFM69_REG_PALEVEL, palevel); - RFM69_DEBUG(PSTR("RFM69:PTX:LEVEL=%" PRIi8 " dBm\n"),newPowerLevel); - return true; -} - -LOCAL void RFM69_setAddress(const uint8_t addr) -{ - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY); - RFM69.address = addr; - RFM69_writeReg(RFM69_REG_NODEADRS, addr); -} - -LOCAL uint8_t RFM69_getAddress(void) -{ - return RFM69.address; -} - -LOCAL bool RFM69_setRadioMode(const rfm69_radio_mode_t newRadioMode) -{ - if (RFM69.radioMode == newRadioMode) { - // no change - return false; - } - - uint8_t regMode; - - if (newRadioMode == RFM69_RADIO_MODE_STDBY) { - regMode = RFM69_OPMODE_SEQUENCER_ON | RFM69_OPMODE_LISTEN_OFF | RFM69_OPMODE_STANDBY; - } else if (newRadioMode == RFM69_RADIO_MODE_SLEEP) { - regMode = RFM69_OPMODE_SEQUENCER_OFF | RFM69_OPMODE_LISTEN_OFF | RFM69_OPMODE_SLEEP; - } else if (newRadioMode == RFM69_RADIO_MODE_RX) { - RFM69.dataReceived = false; - RFM69.ackReceived = false; - regMode = RFM69_OPMODE_SEQUENCER_ON | RFM69_OPMODE_LISTEN_OFF | RFM69_OPMODE_RECEIVER; - RFM69_writeReg(RFM69_REG_DIOMAPPING1, RFM69_DIOMAPPING1_DIO0_01); // Interrupt on PayloadReady, DIO0 - // disable high power settings - RFM69_setHighPowerRegs(false); - RFM69_writeReg(RFM69_REG_PACKETCONFIG2, - (RFM69_readReg(RFM69_REG_PACKETCONFIG2) & 0xFB) | RFM69_PACKET2_RXRESTART); // avoid RX deadlocks - } else if (newRadioMode == RFM69_RADIO_MODE_TX) { - regMode = RFM69_OPMODE_SEQUENCER_ON | RFM69_OPMODE_LISTEN_OFF | RFM69_OPMODE_TRANSMITTER; - RFM69_writeReg(RFM69_REG_DIOMAPPING1, RFM69_DIOMAPPING1_DIO0_00); // Interrupt on PacketSent, DIO0 - RFM69_setHighPowerRegs(RFM69.powerLevel >= (rfm69_powerlevel_t)RFM69_HIGH_POWER_DBM); - } else if (newRadioMode == RFM69_RADIO_MODE_SYNTH) { - regMode = RFM69_OPMODE_SEQUENCER_ON | RFM69_OPMODE_LISTEN_OFF | RFM69_OPMODE_SYNTHESIZER; - } else { - regMode = RFM69_OPMODE_SEQUENCER_ON | RFM69_OPMODE_LISTEN_OFF | RFM69_OPMODE_STANDBY; - } - - // set new mode - RFM69_writeReg(RFM69_REG_OPMODE, regMode); - - // Waking from sleep mode may take longer - if (RFM69.radioMode == RFM69_RADIO_MODE_SLEEP) { - // wait for ModeReady - if (!RFM69_isModeReady()) { - return false; - } - } - RFM69.radioMode = newRadioMode; - return true; -} - -LOCAL void RFM69_powerUp(void) -{ -#if defined(MY_RFM69_POWER_PIN) - RFM69_DEBUG(PSTR("RFM69:PWU\n")); // power up radio - hwDigitalWrite(MY_RFM69_POWER_PIN, HIGH); - delay(RFM69_POWERUP_DELAY_MS); -#endif -} -LOCAL void RFM69_powerDown(void) -{ -#if defined(MY_RFM69_POWER_PIN) - RFM69_DEBUG(PSTR("RFM69:PWD\n")); // power down radio - hwDigitalWrite(MY_RFM69_POWER_PIN, LOW); -#endif -} - -LOCAL bool RFM69_sleep(void) -{ - RFM69_DEBUG(PSTR("RFM69:RSL\n")); // put radio to sleep - return RFM69_setRadioMode(RFM69_RADIO_MODE_SLEEP); -} - -LOCAL bool RFM69_standBy(void) -{ - RFM69_DEBUG(PSTR("RFM69:RSB\n")); // put radio to standby - return RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY); -} - - -// should be called immediately after reception in case sender wants ACK -LOCAL void RFM69_sendACK(const uint8_t recipient, const rfm69_sequenceNumber_t sequenceNumber, - const rfm69_RSSI_t RSSI) -{ - RFM69_DEBUG(PSTR("RFM69:SAC:SEND ACK,TO=%" PRIu8 ",RSSI=%" PRIi16 "\n"),recipient, - RFM69_internalToRSSI(RSSI)); - rfm69_ack_t ACK; - ACK.sequenceNumber = sequenceNumber; - ACK.RSSI = RSSI; - rfm69_controlFlags_t flags = 0u; // reset flags - RFM69_setACKReceived(flags, true); - RFM69_setACKRSSIReport(flags, true); - (void)RFM69_send(recipient, (uint8_t *)&ACK, sizeof(rfm69_ack_t), flags); -} - -LOCAL bool RFM69_executeATC(const rfm69_RSSI_t currentRSSI, const rfm69_RSSI_t targetRSSI) -{ - // RSSI range -80..-70 = internal representation 160(l)..140(u) - rfm69_powerlevel_t newPowerLevel = RFM69.powerLevel; - const rfm69_RSSI_t uRange = targetRSSI - RFM69_RSSItoInternal(RFM69_ATC_TARGET_RANGE_DBM); - const rfm69_RSSI_t lRange = targetRSSI + RFM69_RSSItoInternal(RFM69_ATC_TARGET_RANGE_DBM); - if (currentRSSI > lRange && newPowerLevel < RFM69_MAX_POWER_LEVEL_DBM) { - // increase transmitter power - newPowerLevel++; - } else if (currentRSSI < uRange && newPowerLevel > RFM69_MIN_POWER_LEVEL_DBM) { - // decrease transmitter power - newPowerLevel--; - } else { - // nothing to adjust - return false; - } - RFM69_DEBUG(PSTR("RFM69:ATC:ADJ TXL,cR=%" PRIi16 ",tR=%" PRIi16 "..%" PRIi16 ",TXL=%" PRIi8 "\n"), - RFM69_internalToRSSI(currentRSSI), RFM69_internalToRSSI(lRange), RFM69_internalToRSSI(uRange), - RFM69.powerLevel); - return RFM69_setTxPowerLevel(newPowerLevel); -} - -LOCAL void RFM69_ATCmode(const bool onOff, const int16_t targetRSSI) -{ - RFM69.ATCenabled = onOff; - RFM69.ATCtargetRSSI = RFM69_RSSItoInternal(targetRSSI); -} - - -LOCAL bool RFM69_sendWithRetry(const uint8_t recipient, const void *buffer, - const uint8_t bufferSize, const bool noACK) -{ - for (uint8_t retry = 0; retry < RFM69_RETRIES; retry++) { - RFM69_DEBUG(PSTR("RFM69:SWR:SEND,TO=%" PRIu8 ",SEQ=%" PRIu16 ",RETRY=%" PRIu8 "\n"), recipient, - RFM69.txSequenceNumber,retry); - rfm69_controlFlags_t flags = 0u; // reset all flags - RFM69_setACKRequested(flags, !noACK); - RFM69_setACKRSSIReport(flags, RFM69.ATCenabled); - (void)RFM69_send(recipient, (uint8_t *)buffer, bufferSize, flags, !retry); - if (noACK) { - // no ACK requested - return true; - } - // radio is in RX - const uint32_t enterMS = hwMillis(); - while (hwMillis() - enterMS < RFM69_RETRY_TIMEOUT_MS && !RFM69.dataReceived) { - RFM69_handler(); - if (RFM69.ackReceived) { - // radio is in stdby - const uint8_t ACKsender = RFM69.currentPacket.header.sender; - const rfm69_sequenceNumber_t ACKsequenceNumber = RFM69.currentPacket.ACK.sequenceNumber; - const rfm69_controlFlags_t ACKflags = RFM69.currentPacket.header.controlFlags; - const rfm69_RSSI_t ACKRSSI = RFM69.currentPacket.ACK.RSSI; - RFM69.ackReceived = false; - // packet read, back to RX - RFM69_setRadioMode(RFM69_RADIO_MODE_RX); - if (ACKsender == recipient && ACKsequenceNumber == RFM69.txSequenceNumber) { - RFM69_DEBUG(PSTR("RFM69:SWR:ACK,FROM=%" PRIu8 ",SEQ=%" PRIu8 ",RSSI=%" PRIi16 "\n"), ACKsender, - ACKsequenceNumber, - RFM69_internalToRSSI(ACKRSSI)); - - // ATC - if (RFM69.ATCenabled && RFM69_getACKRSSIReport(ACKflags)) { - (void)RFM69_executeATC(ACKRSSI, RFM69.ATCtargetRSSI); - } - return true; - } // seq check - } - } - RFM69_DEBUG(PSTR("!RFM69:SWR:NACK\n")); - } - return false; -} - -LOCAL int16_t RFM69_getSendingRSSI(void) -{ - // own RSSI, as measured by the recipient - ACK part - if (RFM69_getACKRSSIReport(RFM69.currentPacket.header.controlFlags)) { - return RFM69_internalToRSSI(RFM69.currentPacket.ACK.RSSI); - } else { - // not valid - return 127; - } -} - -LOCAL int16_t RFM69_getReceivingRSSI(void) -{ - // RSSI from sender - return RFM69_internalToRSSI(RFM69.currentPacket.RSSI); -} - -LOCAL bool RFM69_setTxPowerPercent(uint8_t newPowerPercent) -{ - newPowerPercent = min(newPowerPercent, (uint8_t)100); // limit - const rfm69_powerlevel_t newPowerLevel = static_cast - (RFM69_MIN_POWER_LEVEL_DBM + (RFM69_MAX_POWER_LEVEL_DBM - - RFM69_MIN_POWER_LEVEL_DBM) * (newPowerPercent / 100.0f)); - RFM69_DEBUG(PSTR("RFM69:SPP:PCT=%" PRIu8 ",TX LEVEL=%" PRIi8 "\n"), newPowerPercent,newPowerLevel); - return RFM69_setTxPowerLevel(newPowerLevel); -} - - - -LOCAL rfm69_powerlevel_t RFM69_getTxPowerLevel(void) -{ - // report TX level in dBm - return RFM69.powerLevel; -} - -LOCAL uint8_t RFM69_getTxPowerPercent(void) -{ - // report TX level in % - const uint8_t result = static_cast(100.0f * (RFM69.powerLevel - - RFM69_MIN_POWER_LEVEL_DBM) / - (RFM69_MAX_POWER_LEVEL_DBM - - RFM69_MIN_POWER_LEVEL_DBM)); - return result; -} - -LOCAL bool RFM69_sanityCheck(void) -{ - bool result = true; // default - result &= RFM69_readReg(RFM69_REG_RSSITHRESH) == RFM69_RSSITHRESH_VALUE; - result &= RFM69_readReg(RFM69_REG_SYNCVALUE1) == RFM69_SYNCVALUE1; - result &= RFM69_readReg(RFM69_REG_SYNCVALUE2) == MY_RFM69_NETWORKID; - return result; -} - -LOCAL void RFM69_setConfiguration(void) -{ - const uint8_t rfm69_modem_config[] = { MY_RFM69_MODEM_CONFIGURATION }; - const uint8_t CONFIG[][2] = { - { RFM69_REG_OPMODE, RFM69_OPMODE_SEQUENCER_ON | RFM69_OPMODE_LISTEN_OFF | RFM69_OPMODE_STANDBY }, - { RFM69_REG_DATAMODUL, rfm69_modem_config[0] }, - { RFM69_REG_BITRATEMSB, rfm69_modem_config[1] }, - { RFM69_REG_BITRATELSB, rfm69_modem_config[2] }, - { RFM69_REG_FDEVMSB, rfm69_modem_config[3] }, - { RFM69_REG_FDEVLSB, rfm69_modem_config[4] }, - { RFM69_REG_LNA, RFM69_LNA_ZIN_200 | RFM69_LNA_CURRENTGAIN }, - { RFM69_REG_RXBW, rfm69_modem_config[5] }, - { RFM69_REG_AFCBW, rfm69_modem_config[5] }, // same as rxbw, experimental, based on datasheet - //{ RFM69_REG_DIOMAPPING1, RFM69_DIOMAPPING1_DIO0_01 }, - { RFM69_REG_DIOMAPPING2, RFM69_DIOMAPPING2_CLKOUT_OFF }, - { RFM69_REG_IRQFLAGS2, RFM69_IRQFLAGS2_FIFOOVERRUN }, // clear FIFO and flags - { RFM69_REG_RSSITHRESH, RFM69_RSSITHRESH_VALUE }, - { RFM69_REG_PREAMBLEMSB, RFM69_PREAMBLESIZE_MSB_VALUE }, - { RFM69_REG_PREAMBLELSB, RFM69_PREAMBLESIZE_LSB_VALUE }, - { RFM69_REG_SYNCCONFIG, RFM69_SYNC_ON | RFM69_SYNC_FIFOFILL_AUTO | RFM69_SYNC_SIZE_2 | RFM69_SYNC_TOL_0 }, - { RFM69_REG_SYNCVALUE1, RFM69_SYNCVALUE1 }, - { RFM69_REG_SYNCVALUE2, MY_RFM69_NETWORKID }, - { RFM69_REG_PACKETCONFIG1, rfm69_modem_config[6] }, - { RFM69_REG_PAYLOADLENGTH, RFM69_MAX_PACKET_LEN }, // in variable length mode: the max frame size, not used in TX - { RFM69_REG_NODEADRS, RFM69_BROADCAST_ADDRESS }, // init - { RFM69_REG_BROADCASTADRS, RFM69_BROADCAST_ADDRESS }, - { RFM69_REG_FIFOTHRESH, RFM69_FIFOTHRESH_TXSTART_FIFOTHRESH | (RFM69_HEADER_LEN - 1) }, // start transmitting when rfm69 header loaded, fifo level irq when header bytes received (irq asserted when n bytes exceeded) - { RFM69_REG_PACKETCONFIG2, RFM69_PACKET2_RXRESTARTDELAY_2BITS | RFM69_PACKET2_AUTORXRESTART_OFF | RFM69_PACKET2_AES_OFF }, - { RFM69_REG_TESTDAGC, RFM69_DAGC_IMPROVED_LOWBETA0 }, // continuous DAGC mode, use 0x30 if afc offset == 0 - { 255, 0} - }; - for (uint8_t i = 0; CONFIG[i][0] != 255; i++) { - RFM69_writeReg(CONFIG[i][0], CONFIG[i][1]); - } -} - -LOCAL bool RFM69_isModeReady(void) -{ - uint16_t timeout = 0xFFFF; - while (!(RFM69_readReg(RFM69_REG_IRQFLAGS1) & RFM69_IRQFLAGS1_MODEREADY) && timeout--) { - }; - return timeout; -} - -LOCAL void RFM69_encrypt(const char *key) -{ - (void)RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY); - if (key != NULL) { - RFM69_burstWriteReg(RFM69_REG_AESKEY1, key, 16); - } - RFM69_writeReg(RFM69_REG_PACKETCONFIG2, - (RFM69_readReg(RFM69_REG_PACKETCONFIG2) & 0xFE) | (key ? RFM69_PACKET2_AES_ON : - RFM69_PACKET2_AES_OFF)); -} - -LOCAL rfm69_RSSI_t RFM69_readRSSI(const bool forceTrigger) -{ - // RssiStart command and RssiDone flags are not usable when DAGC is turned on - /*if (forceTrigger) { - RFM69_writeReg(RFM69_REG_RSSICONFIG, RFM69_RSSI_START); - uint16_t timeout = 0xFFFF; - while (!(RFM69_readReg(RFM69_REG_RSSICONFIG) & RFM69_RSSI_DONE) && timeout--) { - }; - } - */ - (void)forceTrigger; - return (rfm69_RSSI_t)RFM69_readReg(RFM69_REG_RSSIVALUE); -} - -LOCAL void RFM69_readAllRegs(void) -{ -#ifdef RFM69_REGISTER_DETAIL - int16_t capVal; - - //... State Variables for intelligent decoding - uint8_t modeFSK = 0; - int16_t bitRate = 0; - int16_t freqDev = 0; - int32_t freqCenter = 0; -#endif - - RFM69_DEBUG(PSTR("RFM69:DUMP:Registers Address | HEX value \n")); - - for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++) { - uint8_t regVal = RFM69_readReg(regAddr); - RFM69_DEBUG(PSTR("RFM69:DUMP:REG=0x%02x Value=0x%02x\n"), regAddr, regVal); -#ifdef RFM69_REGISTER_DETAIL - switch (regAddr) { - case 0x1: { - RFM69_DEBUG(PSTR("RFM69:DUMP:REG=0x%02x Controls the automatic Sequencer(see section 4.2)\n"), - regAddr); - - if (0x80 & regVal) { - RFM69_DEBUG(PSTR("RFM69:DUMP:SequencerOff : 1 -> Mode is forced by the user\n")); - } else { - RFM69_DEBUG( - PSTR("RFM69:DUMP:SequencerOff : 0 -> Operating mode as selected with Mode bits in RegOpMode is automatically reached with the Sequencer\n")); - } - - RFM69_DEBUG(PSTR("RFM69:DUMP:Enables Listen mode, should be enabled whilst in Standby mode\n")); - if (0x40 & regVal) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenOn : 1 -> On\n")); - } else { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenOn : 0->Off(see section 4.3)\n")); - } - - RFM69_DEBUG( - PSTR("RFM69:DUMP:Aborts Listen mode when set together with ListenOn=0 See section 4.3.4 for details (Always reads 0.)\n")); - if (0x20 & regVal) { - RFM69_DEBUG( - PSTR("RFM69:DUMP:ERROR - ListenAbort should NEVER return 1 this is a write only register\n")); - } - - RFM69_DEBUG(PSTR("RFM69:DUMP:Transceiver's operating modes\n")); - capVal = (regVal >> 2) & 0x7; - if (capVal == 0b000) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Mode : 000 -> Sleep mode (SLEEP)\n")); - } else if (capVal == 0b001) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Mode : 001 -> Standby mode (STDBY)\n")); - } else if (capVal == 0b010) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Mode : 010 -> Frequency Synthesizer mode (FS)\n")); - } else if (capVal == 0b011) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Mode : 011 -> Transmitter mode (TX)\n")); - } else if (capVal == 0b100) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Mode : 100 -> Receiver Mode (RX)\n")); - } else { - RFM69_DEBUG(PSTR("RFM69:DUMP:Mode : %d capVal \n"), capVal); - - } - break; - } - - case 0x2: { - RFM69_DEBUG(PSTR("RFM69:DUMP:REG=0x%02x Data Processing mode \n"), regAddr); - - capVal = (regVal >> 5) & 0x3; - if (capVal == 0b00) { - RFM69_DEBUG(PSTR("RFM69:DUMP:DataMode : 00 -> Packet mode\n")); - } else if (capVal == 0b01) { - RFM69_DEBUG(PSTR("RFM69:DUMP:DataMode : 01 -> reserved\n")); - } else if (capVal == 0b10) { - RFM69_DEBUG(PSTR("RFM69:DUMP:DataMode : 10 -> Continuous mode with bit synchronizer\n")); - } else if (capVal == 0b11) { - RFM69_DEBUG(PSTR("RFM69:DUMP:DataMode : 11 -> Continuous mode without bit synchronizer\n")); - } - - RFM69_DEBUG(PSTR("RFM69:DUMP:Modulation scheme\n")); - capVal = (regVal >> 3) & 0x3; - if (capVal == 0b00) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Modulation Type : 00 -> FSK\n")); - modeFSK = 1; - } else if (capVal == 0b01) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Modulation Type : 01 -> OOK\n")); - } else if (capVal == 0b10) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Modulation Type : 10 -> reserved\n")); - } else if (capVal == 0b11) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Modulation Type : 11 -> reserved\n")); - } - - if (modeFSK) { - RFM69_DEBUG(PSTR("RFM69:DUMP:Data shaping : in FSK\n")); - } else { - RFM69_DEBUG(PSTR("RFM69:DUMP:Data shaping : in OOK\n")); - } - - capVal = regVal & 0x3; - if (modeFSK) { - if (capVal == 0b00) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ModulationShaping : 00 -> no shaping\n")); - } else if (capVal == 0b01) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ModulationShaping : 01 -> Gaussian filter, BT = 1.0\n")); - } else if (capVal == 0b10) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ModulationShaping : 10 -> Gaussian filter, BT = 0.5\n")); - } else if (capVal == 0b11) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ModulationShaping : 11 -> Gaussian filter, BT = 0.3\n")); - } - } else { - if (capVal == 0b00) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ModulationShaping : 00 -> no shaping\n")); - } else if (capVal == 0b01) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ModulationShaping : 01 -> filtering with f(cutoff) = BR\n")); - } else if (capVal == 0b10) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ModulationShaping : 10 -> filtering with f(cutoff) = 2*BR\n")); - } else if (capVal == 0b11) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ModulationShaping : ERROR - 11 is reserved\n")); - } - } - - break; - } - - case 0x3: { - bitRate = (regVal << 8); - break; - } - - case 0x4: { - bitRate |= regVal; - RFM69_DEBUG( - PSTR("RFM69:DUMP:REG=0x%02x Bit Rate (Chip Rate when Manchester encoding is enabled)\n"), regAddr); - - uint32_t val = 32UL * 1000UL * 1000UL / bitRate; - RFM69_DEBUG(PSTR("RFM69:DUMP:BitRate : %lu\n"), val); - break; - } - - case 0x5: { - freqDev = ((regVal & 0x3f) << 8); - break; - } - - case 0x6: { - freqDev |= regVal; - - uint32_t val = 61UL * freqDev; - RFM69_DEBUG(PSTR("RFM69:DUMP:REG=0x%02x Frequency deviation\n"), regAddr); - RFM69_DEBUG(PSTR("RFM69:DUMP:Fdev : %lu\n"), val); - break; - } - - case 0x7: { - uint32_t tempVal = regVal; - freqCenter = (tempVal << 16); - break; - } - - case 0x8: { - uint32_t tempVal = regVal; - freqCenter = freqCenter | (tempVal << 8); - break; - } - - case 0x9: { - freqCenter = freqCenter | regVal; - uint32_t val = 61UL * freqCenter; - RFM69_DEBUG(PSTR("RFM69:DUMP:REG=0x%02x RF Carrier frequency \n"), regAddr); - RFM69_DEBUG(PSTR("RFM69:DUMP:FRF : %lu\n"), val); - break; - } - - case 0xa: { - RFM69_DEBUG(PSTR("RFM69:DUMP:REG=0x%02x RC calibration control & status\n"), regAddr); - if (0x40 & regVal) { - RFM69_DEBUG(PSTR("RFM69:DUMP:RcCalDone : 1 -> RC calibration is over\n")); - } else { - RFM69_DEBUG(PSTR("RFM69:DUMP:RcCalDone : 0 -> RC calibration is in progress\n")); - } - - break; - } - - case 0xb: { - RFM69_DEBUG( - PSTR("RFM69:DUMP:REG=0x%02x Improved AFC routine for signals with modulation index lower than 2. Refer to section 3.4.16 for details\n"), - regAddr); - if (0x20 & regVal) { - RFM69_DEBUG(PSTR("RFM69:DUMP:AfcLowBetaOn : 1 -> Improved AFC routine\n")); - } else { - RFM69_DEBUG(PSTR("RFM69:DUMP:AfcLowBetaOn : 0 -> Standard AFC routine\n")); - } - break; - } - - case 0xc: { - RFM69_DEBUG(PSTR("RFM69:DUMP:REG=0x%02x Reserved\n"), regAddr); - break; - } - - case 0xd: { - byte val; - RFM69_DEBUG(PSTR("RFM69:DUMP:REG=0x%02x Resolution of Listen mode Idle time (calibrated RC osc)\n"), - regAddr); - val = regVal >> 6; - if (val == 0b00) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenResolIdle : 00 -> reserved\n")); - } else if (val == 0b01) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenResolIdle : 01 -> 64 us\n")); - } else if (val == 0b10) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenResolIdle : 10 -> 4.1 ms\n")); - } else if (val == 0b11) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenResolIdle : 11 -> 262 ms\n")); - } - - RFM69_DEBUG(PSTR("RFM69:DUMP:Resolution of Listen mode Rx time (calibrated RC osc)\n")); - val = (regVal >> 4) & 0x3; - if (val == 0b00) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenResolRx : 00 -> reserved\n")); - } else if (val == 0b01) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenResolRx : 01 -> 64 us\n")); - } else if (val == 0b10) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenResolRx : 10 -> 4.1 ms\n")); - } else if (val == 0b11) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenResolRx : 11 -> 262 ms\n")); - } - - RFM69_DEBUG(PSTR("RFM69:DUMP:Criteria for packet acceptance in Listen mode\n")); - if (0x8 & regVal) { - RFM69_DEBUG( - PSTR("RFM69:DUMP:ListenCriteria : 1 -> signal strength is above RssiThreshold and SyncAddress matched\n")); - } else { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenCriteria : 0 -> signal strength is above RssiThreshold\n")); - } - - - RFM69_DEBUG(PSTR("RFM69:DUMP:Action taken after acceptance of a packet in Listen mode\n")); - val = (regVal >> 1) & 0x3; - if (val == 0b00) { - RFM69_DEBUG( - PSTR("RFM69:DUMP:ListenEnd : 00 -> chip stays in Rx mode. Listen mode stops and must be disabled (see section 4.3)\n")); - } else if (val == 0b01) { - RFM69_DEBUG( - PSTR("RFM69:DUMP:ListenEnd : 01 -> chip stays in Rx mode until PayloadReady or Timeout interrupt occurs. It then goes to the mode defined by Mode. Listen mode stops and must be disabled (see section 4.3)\n")); - } else if (val == 0b10) { - RFM69_DEBUG( - PSTR("RFM69:DUMP:ListenEnd : 10 -> chip stays in Rx mode until PayloadReady or Timeout occurs. Listen mode then resumes in Idle state. FIFO content is lost at next Rx wakeup.\n")); - } else if (val == 0b11) { - RFM69_DEBUG(PSTR("RFM69:DUMP:ListenEnd : 11 -> Reserved\n")); - } - break; - } - - default: { - } - } -#endif - (void)regVal; - } -} diff --git a/lib/MySensors/hal/transport/RFM69/driver/new/RFM69_new.h b/lib/MySensors/hal/transport/RFM69/driver/new/RFM69_new.h deleted file mode 100644 index 5f5b0b29..00000000 --- a/lib/MySensors/hal/transport/RFM69/driver/new/RFM69_new.h +++ /dev/null @@ -1,561 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * RFM69 driver refactored for MySensors - * - * Based on : - * - LowPowerLab RFM69 Lib Copyright Felix Rusu (2014), felix@lowpowerlab.com - * - Automatic Transmit Power Control class derived from RFM69 library. - * Discussion and details in this forum post: https://lowpowerlab.com/forum/index.php/topic,688.0.html - * Copyright Thomas Studwell (2014,2015) - * - MySensors generic radio driver implementation Copyright (C) 2017, 2018 Olivier Mauti - * - * Changes by : @tekka, @scalz, @marceloagno - * - * Definitions for Semtech SX1231/H radios: - * https://www.semtech.com/uploads/documents/sx1231.pdf - * https://www.semtech.com/uploads/documents/sx1231h.pdf - */ - - -/** -* @file RFM69_new.h -* -* @defgroup RFM69Newgrp RFM69New -* @ingroup internals -* @{ -* -* RFM69 driver-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE -* - [!] Exclamation mark is prepended in case of error -* -* |E| SYS | SUB | Message | Comment -* |-|-------|------|--------------------------------------|----------------------------------------------------------------------------------- -* | | RFM69 | INIT | | Initialise RFM69 radio -* | | RFM69 | INIT | PIN,CS=%%d,IQP=%%d,IQN=%%d[,RST=%%d] | Pin configuration: chip select (CS), IRQ pin (IQP), IRQ number (IQN), Reset (RST) -* | | RFM69 | INIT | HWV=%%d | HW version, see datasheet chapter 9 -* |!| RFM69 | INIT | SANCHK FAIL | Sanity check failed, check wiring or replace module -* | | RFM69 | PTX | NO ADJ | TX power level, no adjustment -* | | RFM69 | PTX | LEVEL=%%d dbM | TX power level, set to (LEVEL) dBm -* | | RFM69 | SAC | SEND ACK,TO=%%d,RSSI=%%d | ACK sent to (TO), RSSI of incoming message (RSSI) -* | | RFM69 | ATC | ADJ TXL,cR=%%d,tR=%%d..%%d,TXL=%%d | Adjust TX level, current RSSI (cR), target RSSI range (tR), TX level (TXL) -* | | RFM69 | SWR | SEND,TO=%%d,SEQ=%%d,RETRY=%%d | Send to (TO), sequence number (SWQ), retry if no ACK received (RETRY) -* | | RFM69 | SWR | ACK,FROM=%%d,SEQ=%%d,RSSI=%%d | ACK received from (FROM), sequence nr (SEQ), ACK RSSI (RSSI) -* |!| RFM69 | SWR | NACK | Message sent, no ACK received -* | | RFM69 | SPP | PCT=%%d,TX LEVEL=%%d | Set TX level, input TX percent (PCT) -* | | RFM69 | RSL | | Radio in sleep mode -* | | RFM69 | RSB | | Radio in standby mode -* | | RFM69 | PWD | | Power down radio -* | | RFM69 | PWU | | Power up radio -* -* @brief API declaration for RFM69 -* -*/ - -#ifndef _RFM69_h -#define _RFM69_h - -#include "RFM69registers_new.h" - -#if !defined(RFM69_SPI) -#define RFM69_SPI hwSPI //!< default SPI -#endif - -#if defined(ARDUINO_ARCH_AVR) -#if defined(__AVR_ATmega32U4__) -#define DEFAULT_RFM69_IRQ_PIN (3) //!< DEFAULT_RFM69_IRQ_PIN -#else -#define DEFAULT_RFM69_IRQ_PIN (2) //!< DEFAULT_RFM69_IRQ_PIN -#endif -#elif defined(ARDUINO_ARCH_ESP8266) -#define DEFAULT_RFM69_IRQ_PIN (5) //!< DEFAULT_RFM69_IRQ_PIN -#elif defined(ARDUINO_ARCH_ESP32) -#define DEFAULT_RFM69_IRQ_PIN (16) //!< DEFAULT_RFM69_IRQ_PIN -#define DEFAULT_RFM69_IRQ_NUM digitalPinToInterrupt(DEFAULT_RFM69_IRQ_PIN) //!< DEFAULT_RFM69_IRQ_NUM -#elif defined(ARDUINO_ARCH_SAMD) -#define DEFAULT_RFM69_IRQ_PIN (2) //!< DEFAULT_RFM69_IRQ_PIN -#elif defined(LINUX_ARCH_RASPBERRYPI) -#define DEFAULT_RFM69_IRQ_PIN (22) //!< DEFAULT_RFM69_IRQ_PIN -#elif defined(ARDUINO_ARCH_STM32F1) -#define DEFAULT_RFM69_IRQ_PIN (PA3) //!< DEFAULT_RFM69_IRQ_PIN -#elif defined(TEENSYDUINO) -#define DEFAULT_RFM69_IRQ_PIN (8) //!< DEFAULT_RFM69_IRQ_PIN -#else -#define DEFAULT_RFM69_IRQ_PIN (2) //!< DEFAULT_RFM69_IRQ_PIN -#endif - -#define DEFAULT_RFM69_CS_PIN (SS) //!< DEFAULT_RFM69_CS_PIN - -// SPI settings -#define RFM69_SPI_DATA_ORDER MSBFIRST //!< SPI data order -#define RFM69_SPI_DATA_MODE SPI_MODE0 //!< SPI mode - -// Additional radio settings -#define RFM69_SYNCVALUE1 (0x2D) //!< Make this compatible with sync1 byte of RFM12B lib - -#if (MY_RFM69HW==true) -// RFM69H(C)W -#define RFM69_VERSION_HW //!< HW version -#define RFM69_MIN_POWER_LEVEL_DBM ((rfm69_powerlevel_t)-2) //!< min. power level, -2dBm -#if defined(MY_RFM69_MAX_POWER_LEVEL_DBM) -#define RFM69_MAX_POWER_LEVEL_DBM MY_RFM69_MAX_POWER_LEVEL_DBM //!< MY_RFM69_MAX_POWER_LEVEL_DBM -#else -#define RFM69_MAX_POWER_LEVEL_DBM ((rfm69_powerlevel_t)20) //!< max. power level, +20dBm -#endif -#else -// RFM69(C)W -#define RFM69_MIN_POWER_LEVEL_DBM ((rfm69_powerlevel_t)-18) //!< min. power level, -18dBm -#if defined(MY_RFM69_MAX_POWER_LEVEL_DBM) -#define RFM69_MAX_POWER_LEVEL_DBM MY_RFM69_MAX_POWER_LEVEL_DBM //!< MY_RFM69_MAX_POWER_LEVEL_DBM -#else -#define RFM69_MAX_POWER_LEVEL_DBM ((rfm69_powerlevel_t)13) //!< max. power level, +13dBm -#endif -#endif - -#define RFM69_FIFO_SIZE (0xFFu) //!< Max number of bytes the Rx/Tx FIFO can hold -#define RFM69_MAX_PACKET_LEN (0x40u) //!< This is the maximum number of bytes that can be carried -#define RFM69_ATC_TARGET_RANGE_DBM (2u) //!< ATC target range +/- dBm -#define RFM69_PACKET_HEADER_VERSION (1u) //!< RFM69 packet header version -#define RFM69_MIN_PACKET_HEADER_VERSION (1u) //!< Minimal RFM69 packet header version - -#define RFM69_RETRIES (5u) //!< Retries in case of failed transmission -#define RFM69_RETRY_TIMEOUT_MS (200ul) //!< Timeout for ACK, adjustments needed if modem configuration changed (air time different) -#define RFM69_MODE_READY_TIMEOUT_MS (50ul) //!< Timeout for mode ready - -#define RFM69_ACK_REQUESTED (7u) //!< RFM69 header, controlFlag, bit 7 -#define RFM69_ACK_RECEIVED (6u) //!< RFM69 header, controlFlag, bit 6 -#define RFM69_ACK_RSSI_REPORT (5u) //!< RFM69 header, controlFlag, bit 5 - -#define RFM69_BROADCAST_ADDRESS (255u) //!< Broadcasting address -#define RFM69_TARGET_RSSI_DBM (-75) //!< RSSI target -#define RFM69_HIGH_POWER_DBM (18u) //!< High power threshold, dBm - -#if !defined(MY_RFM69_TX_TIMEOUT_MS) -#define MY_RFM69_TX_TIMEOUT_MS (2*1000ul) //!< Timeout for packet sent -#endif - -// CSMA settings -#if !defined(MY_RFM69_CSMA_LIMIT_DBM) -#define MY_RFM69_CSMA_LIMIT_DBM (-95) //!< upper RX signal sensitivity threshold in dBm for carrier sense access -#endif -#if !defined(MY_RFM69_CSMA_TIMEOUT_MS) -#define MY_RFM69_CSMA_TIMEOUT_MS (500ul) //!< CSMA timeout -#endif -// powerup delay -#define RFM69_POWERUP_DELAY_MS (100ul) //!< Power up delay, allow VCC to settle, transport to become fully operational - -// available frequency bands, non trivial values to avoid misconfiguration -#define RFM69_315MHZ (315000000ul) //!< RFM69_315MHZ -#define RFM69_433MHZ (433920000ul) //!< RFM69_433MHZ, center frequency 433.92 MHz -#define RFM69_865MHZ (865500000ul) //!< RFM69_865MHZ, center frequency 865.5 MHz -#define RFM69_868MHZ (868000000ul) //!< RFM69_868MHZ -#define RFM69_915MHZ (915000000ul) //!< RFM69_915MHZ - -#define RFM69_COURSE_TEMP_COEF (-90) //!< puts the temperature reading in the ballpark, user can fine tune the returned value -#define RFM69_FXOSC (32*1000000ul) //!< OSC freq, 32MHz -#define RFM69_FSTEP (RFM69_FXOSC / 524288.0f) //!< FXOSC / 2^19 = 32MHz / 2^19 (p13 in datasheet) - -// helper macros -#define RFM69_getACKRequested(__value) ((bool)bitRead(__value,RFM69_ACK_REQUESTED)) //!< getACKRequested -#define RFM69_setACKRequested(__value, __flag) bitWrite(__value,RFM69_ACK_REQUESTED,__flag) //!< setACKRequested -#define RFM69_getACKReceived(__value) ((bool)bitRead(__value,RFM69_ACK_RECEIVED)) //!< getACKReceived -#define RFM69_setACKReceived(__value, __flag) bitWrite(__value,RFM69_ACK_RECEIVED,__flag) //!< setACKReceived -#define RFM69_setACKRSSIReport(__value, __flag) bitWrite(__value,RFM69_ACK_RSSI_REPORT,__flag)//!< setACKRSSIReport -#define RFM69_getACKRSSIReport(__value) ((bool)bitRead(__value,RFM69_ACK_RSSI_REPORT)) //!< getACKRSSIReport - -// Register access -#define RFM69_READ_REGISTER (0x7Fu) //!< reading register -#define RFM69_WRITE_REGISTER (0x80u) //!< writing register - -// Modem configuration section -#define RFM69_CONFIG_FSK (RFM69_DATAMODUL_DATAMODE_PACKET | RFM69_DATAMODUL_MODULATIONTYPE_FSK | RFM69_DATAMODUL_MODULATIONSHAPING_00) //!< RFM69_CONFIG_FSK -#define RFM69_CONFIG_GFSK (RFM69_DATAMODUL_DATAMODE_PACKET | RFM69_DATAMODUL_MODULATIONTYPE_FSK | RFM69_DATAMODUL_MODULATIONSHAPING_10) //!< RFM69_CONFIG_GFSK -#define RFM69_CONFIG_OOK (RFM69_DATAMODUL_DATAMODE_PACKET | RFM69_DATAMODUL_MODULATIONTYPE_OOK | RFM69_DATAMODUL_MODULATIONSHAPING_00) //!< RFM69_CONFIG_OOK - -#define RFM69_CONFIG_NOWHITE (RFM69_PACKET1_FORMAT_VARIABLE | RFM69_PACKET1_DCFREE_OFF | RFM69_PACKET1_CRC_ON | RFM69_PACKET1_CRCAUTOCLEAR_ON | RFM69_PACKET1_ADRSFILTERING_NODEBROADCAST) //!< RFM69_CONFIG_NOWHITE -#define RFM69_CONFIG_WHITE (RFM69_PACKET1_FORMAT_VARIABLE | RFM69_PACKET1_DCFREE_WHITENING | RFM69_PACKET1_CRC_ON | RFM69_PACKET1_CRCAUTOCLEAR_ON | RFM69_PACKET1_ADRSFILTERING_NODEBROADCAST) //!< RFM69_CONFIG_WHITE -#define RFM69_CONFIG_MANCHESTER (RFM69_PACKET1_FORMAT_VARIABLE | RFM69_PACKET1_DCFREE_MANCHESTER | RFM69_PACKET1_CRC_ON | RFM69_PACKET1_CRCAUTOCLEAR_ON | RFM69_PACKET1_ADRSFILTERING_NODEBROADCAST) //!< RFM69_CONFIG_MANCHESTER - -#define RFM69_RXBW_111_24_4 (RFM69_RXBW_DCCFREQ_111 | RFM69_RXBW_MANT_24 | RFM69_RXBW_EXP_4) //!< RFM69_RXBW_111_24_4 -#define RFM69_RXBW_111_24_3 (RFM69_RXBW_DCCFREQ_111 | RFM69_RXBW_MANT_24 | RFM69_RXBW_EXP_3) //!< RFM69_RXBW_111_24_3 -#define RFM69_RXBW_111_24_2 (RFM69_RXBW_DCCFREQ_111 | RFM69_RXBW_MANT_24 | RFM69_RXBW_EXP_2) //!< RFM69_RXBW_111_24_2 -#define RFM69_RXBW_111_16_2 (RFM69_RXBW_DCCFREQ_111 | RFM69_RXBW_MANT_16 | RFM69_RXBW_EXP_2) //!< RFM69_RXBW_111_16_2 -#define RFM69_RXBW_111_16_1 (RFM69_RXBW_DCCFREQ_111 | RFM69_RXBW_MANT_16 | RFM69_RXBW_EXP_1) //!< RFM69_RXBW_111_16_1 -#define RFM69_RXBW_111_16_0 (RFM69_RXBW_DCCFREQ_111 | RFM69_RXBW_MANT_16 | RFM69_RXBW_EXP_0) //!< RFM69_RXBW_111_16_0 -#define RFM69_RXBW_010_16_2 (RFM69_RXBW_DCCFREQ_010 | RFM69_RXBW_MANT_16 | RFM69_RXBW_EXP_2) //!< RFM69_RXBW_010_16_2 - -#define RFM69_FSK_BR2_FD5 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_2000, RFM69_BITRATELSB_2000, RFM69_FDEVMSB_5000, RFM69_FDEVLSB_5000, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR2_FD5 -#define RFM69_FSK_BR2_4_FD4_8 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_2400, RFM69_BITRATELSB_2400, RFM69_FDEVMSB_4800, RFM69_FDEVLSB_4800, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR2_4_FD4_8 -#define RFM69_FSK_BR4_8_FD9_6 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_4800, RFM69_BITRATELSB_4800, RFM69_FDEVMSB_9600, RFM69_FDEVLSB_9600, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR4_8_FD9_6 -#define RFM69_FSK_BR9_6_FD19_2 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_9600, RFM69_BITRATELSB_9600, RFM69_FDEVMSB_19200, RFM69_FDEVLSB_19200, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR9_6_FD19_2 -#define RFM69_FSK_BR19_2_FD38_4 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_19200, RFM69_BITRATELSB_19200, RFM69_FDEVMSB_38400, RFM69_FDEVLSB_38400, RFM69_RXBW_111_24_3, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR19_2_FD38_4 -#define RFM69_FSK_BR38_4_FD76_8 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_38400, RFM69_BITRATELSB_38400, RFM69_FDEVMSB_76800, RFM69_FDEVLSB_76800, RFM69_RXBW_111_24_2, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR38_4_FD76_8 -#define RFM69_FSK_BR55_5_FD50 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_55555, RFM69_BITRATELSB_55555, RFM69_FDEVMSB_50000, RFM69_FDEVLSB_50000, RFM69_RXBW_111_16_2, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR55_5_FD50 -#define RFM69_FSK_BR57_6_FD120 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_57600, RFM69_BITRATELSB_57600, RFM69_FDEVMSB_120000, RFM69_FDEVLSB_120000, RFM69_RXBW_111_16_1, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR57_6_FD120 -#define RFM69_FSK_BR125_FD125 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_125000, RFM69_BITRATELSB_125000, RFM69_FDEVMSB_125000, RFM69_FDEVLSB_125000, RFM69_RXBW_010_16_2, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR125_FD125 -#define RFM69_FSK_BR250_FD250 RFM69_CONFIG_FSK, RFM69_BITRATEMSB_250000, RFM69_BITRATELSB_250000, RFM69_FDEVMSB_250000, RFM69_FDEVLSB_250000, RFM69_RXBW_111_16_0, RFM69_CONFIG_WHITE //!< RFM69_FSK_BR250_FD250 - -#define RFM69_GFSK_BR2_FD5 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_2000, RFM69_BITRATELSB_2000, RFM69_FDEVMSB_5000, RFM69_FDEVLSB_5000, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR2_FD5 -#define RFM69_GFSK_BR2_4_FD4_8 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_2400, RFM69_BITRATELSB_2400, RFM69_FDEVMSB_4800, RFM69_FDEVLSB_4800, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR2_4_FD4_8 -#define RFM69_GFSK_BR4_8_FD9_6 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_4800, RFM69_BITRATELSB_4800, RFM69_FDEVMSB_9600, RFM69_FDEVLSB_9600, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR4_8_FD9_6 -#define RFM69_GFSK_BR9_6_FD19_2 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_9600, RFM69_BITRATELSB_9600, RFM69_FDEVMSB_19200, RFM69_FDEVLSB_19200, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR9_6_FD19_2 -#define RFM69_GFSK_BR19_2_FD38_4 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_19200, RFM69_BITRATELSB_19200, RFM69_FDEVMSB_38400, RFM69_FDEVLSB_38400, RFM69_RXBW_111_24_3, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR19_2_FD38_4 -#define RFM69_GFSK_BR38_4_FD76_8 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_38400, RFM69_BITRATELSB_38400, RFM69_FDEVMSB_76800, RFM69_FDEVLSB_76800, RFM69_RXBW_111_24_2, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR38_4_FD76_8 -#define RFM69_GFSK_BR55_5_FD50 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_55555, RFM69_BITRATELSB_55555, RFM69_FDEVMSB_50000, RFM69_FDEVLSB_50000, RFM69_RXBW_111_16_2, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR55_5_FD50 -#define RFM69_GFSK_BR57_6_FD120 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_57600, RFM69_BITRATELSB_57600, RFM69_FDEVMSB_120000, RFM69_FDEVLSB_120000, RFM69_RXBW_111_16_1, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR57_6_FD120 -#define RFM69_GFSK_BR125_FD125 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_125000, RFM69_BITRATELSB_125000, RFM69_FDEVMSB_125000, RFM69_FDEVLSB_125000, RFM69_RXBW_010_16_2, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR125_FD125 -#define RFM69_GFSK_BR250_FD250 RFM69_CONFIG_GFSK, RFM69_BITRATEMSB_250000, RFM69_BITRATELSB_250000, RFM69_FDEVMSB_250000, RFM69_FDEVLSB_250000, RFM69_RXBW_111_16_0, RFM69_CONFIG_WHITE //!< RFM69_GFSK_BR250_FD250 - -#define RFM69_OOK_BR2_FD5 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_2000, RFM69_BITRATELSB_2000, RFM69_FDEVMSB_5000, RFM69_FDEVLSB_5000, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR2_FD5 -#define RFM69_OOK_BR2_4_FD4_8 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_2400, RFM69_BITRATELSB_2400, RFM69_FDEVMSB_4800, RFM69_FDEVLSB_4800, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR2_4_FD4_8 -#define RFM69_OOK_BR4_8_FD9_6 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_4800, RFM69_BITRATELSB_4800, RFM69_FDEVMSB_9600, RFM69_FDEVLSB_9600, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR4_8_FD9_6 -#define RFM69_OOK_BR9_6_FD19_2 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_9600, RFM69_BITRATELSB_9600, RFM69_FDEVMSB_19200, RFM69_FDEVLSB_19200, RFM69_RXBW_111_24_4, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR9_6_FD19_2 -#define RFM69_OOK_BR19_2_FD38_4 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_19200, RFM69_BITRATELSB_19200, RFM69_FDEVMSB_38400, RFM69_FDEVLSB_38400, RFM69_RXBW_111_24_3, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR19_2_FD38_4 -#define RFM69_OOK_BR38_4_FD76_8 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_38400, RFM69_BITRATELSB_38400, RFM69_FDEVMSB_76800, RFM69_FDEVLSB_76800, RFM69_RXBW_111_24_2, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR38_4_FD76_8 -#define RFM69_OOK_BR55_5_FD50 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_55555, RFM69_BITRATELSB_55555, RFM69_FDEVMSB_50000, RFM69_FDEVLSB_50000, RFM69_RXBW_111_16_2, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR55_5_FD50 -#define RFM69_OOK_BR57_6_FD120 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_57600, RFM69_BITRATELSB_57600, RFM69_FDEVMSB_120000, RFM69_FDEVLSB_120000, RFM69_RXBW_111_16_1, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR57_6_FD120 -#define RFM69_OOK_BR125_FD125 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_125000, RFM69_BITRATELSB_125000, RFM69_FDEVMSB_125000, RFM69_FDEVLSB_125000, RFM69_RXBW_010_16_2, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR125_FD125 -#define RFM69_OOK_BR250_FD250 RFM69_CONFIG_OOK, RFM69_BITRATEMSB_250000, RFM69_BITRATELSB_250000, RFM69_FDEVMSB_250000, RFM69_FDEVLSB_250000, RFM69_RXBW_111_16_0, RFM69_CONFIG_WHITE //!< RFM69_OOK_BR250_FD250 - -#if !defined(MY_RFM69_MODEM_CONFIGURATION) -#define MY_RFM69_MODEM_CONFIGURATION RFM69_FSK_BR55_5_FD50 //!< default setting, RFM69_FSK_BR55_5_FD50 -#endif - -/** -* @brief Radio modes -*/ -typedef enum { - RFM69_RADIO_MODE_RX = 0, //!< RX mode - RFM69_RADIO_MODE_TX = 1, //!< TX mode - RFM69_RADIO_MODE_CAD = 2, //!< CAD mode - RFM69_RADIO_MODE_SLEEP = 3, //!< SLEEP mode - RFM69_RADIO_MODE_STDBY = 4, //!< STDBY mode - RFM69_RADIO_MODE_SYNTH = 5, //!< SYNTH mode - RFM69_RADIO_MODE_LISTEN = 6 //!< LISTEN mode -} rfm69_radio_mode_t; - -/** -* @brief Sequence number data type -*/ -typedef uint8_t rfm69_sequenceNumber_t; -/** -* @brief RSSI data type -*/ -typedef uint8_t rfm69_RSSI_t; -/** -* @brief SNR data type -*/ -typedef int8_t rfm69_SNR_t; -/** -* @brief Control flag data type -*/ -typedef uint8_t rfm69_controlFlags_t; -/** -* @brief Power level in dBm -*/ -typedef int8_t rfm69_powerlevel_t; - -/** -* @brief RFM69 header -* IMPORTANT: Do not change order (see datasheet for packet structure) -*/ -typedef struct { - uint8_t packetLen; //!< packet length - uint8_t recipient; //!< payload recipient - uint8_t version; //!< header version (20180128tk: >=3.0.0 fused with controlFlags) - uint8_t sender; //!< payload sender - rfm69_controlFlags_t controlFlags; //!< control flags, used for ACK - rfm69_sequenceNumber_t sequenceNumber; //!< packet sequence number, used for ACK -} __attribute__((packed)) rfm69_header_t; - -/** -* @brief RFM69 ACK packet structure -*/ -typedef struct { - rfm69_sequenceNumber_t sequenceNumber; //!< sequence number - rfm69_RSSI_t RSSI; //!< RSSI -} __attribute__((packed)) rfm69_ack_t; - -#define RFM69_HEADER_LEN sizeof(rfm69_header_t) //!< Size header inside payload -#define RFM69_MAX_PAYLOAD_LEN (RFM69_MAX_PACKET_LEN - RFM69_HEADER_LEN) //!< Max payload length - -/** -* @brief Packet structure -* IMPORTANT: Do not change order -*/ -typedef struct { - union { - struct { - rfm69_header_t header; //!< Packet header - union { - uint8_t payload[RFM69_MAX_PAYLOAD_LEN]; //!< Union: Data Payload, i.e. MySensors message - rfm69_ack_t ACK; //!< Union: ACK payload (internal) - }; - }; - uint8_t data[RFM69_MAX_PACKET_LEN]; //!< RAW data access - }; - uint8_t payloadLen; //!< Length of payload (excluding header) - rfm69_RSSI_t RSSI; //!< RSSI of current packet, RSSI = value - 137 -} __attribute__((packed)) rfm69_packet_t; - -/** -* @brief RFM69 internal variables -*/ -typedef struct { - uint8_t address; //!< Node address - rfm69_packet_t currentPacket; //!< Buffer for current packet - rfm69_sequenceNumber_t txSequenceNumber; //!< RFM69_txSequenceNumber - rfm69_powerlevel_t powerLevel; //!< TX power level dBm - uint8_t ATCtargetRSSI; //!< ATC: target RSSI - // 8 bit - rfm69_radio_mode_t radioMode : 3; //!< current transceiver state - bool dataReceived : 1; //!< data received - bool ackReceived : 1; //!< ACK received - bool ATCenabled : 1; //!< ATC enabled - uint8_t reserved : 2; //!< Reserved -} rfm69_internal_t; - -#define LOCAL static //!< static - -/** -* @brief RFM69_handler -*/ -LOCAL void RFM69_handler(void); - -/** -* @brief Clear flags and FIFO -*/ -LOCAL void RFM69_clearFIFO(void); - -/** -* @brief Check for channel activity -* @return True if channel activity under RFM69_CSMA_LIMIT_DBM -*/ -LOCAL bool RFM69_channelFree(void); - -/** -* @brief RFM69_interruptHandling -*/ -LOCAL void RFM69_interruptHandling(void); - -/** -* @brief Initialise the driver transport hardware and software -* @param frequencyHz Frequency in Hz -* @return True if initialisation succeeded -*/ -LOCAL bool RFM69_initialise(const uint32_t frequencyHz); - -/** -* @brief Set the driver/node address -* @param addr -*/ -LOCAL void RFM69_setAddress(const uint8_t addr); - -/** -* @brief Get driver/node address -* @return Node address -*/ -LOCAL uint8_t RFM69_getAddress(void); - -/** -* @brief Tests whether a new message is available -* @return True if a new, complete, error-free uncollected message is available to be retreived by @ref RFM69_receive() -*/ -LOCAL bool RFM69_available(void); - -/** -* @brief If a valid message is received, copy it to buf and return length. 0 byte messages are permitted. -* @param buf Location to copy the received message -* @param maxBufSize Max buffer size -* @return Number of bytes -*/ -LOCAL uint8_t RFM69_receive(uint8_t *buf, const uint8_t maxBufSize); - -/** -* @brief RFM69_sendFrame -* @param packet -* @param increaseSequenceCounter -* @return True if packet sent -*/ -LOCAL bool RFM69_sendFrame(rfm69_packet_t *packet, const bool increaseSequenceCounter = true); - -/** -* @brief RFM69_send -* @param recipient -* @param data -* @param len -* @param flags -* @param increaseSequenceCounter -* @return True if frame sent -*/ -LOCAL bool RFM69_send(const uint8_t recipient, uint8_t *data, const uint8_t len, - const rfm69_controlFlags_t flags, const bool increaseSequenceCounter = true); - -/** -* @brief Sets the transmitter and receiver center frequency -* @param frequencyHz Frequency in Hz -*/ -LOCAL void RFM69_setFrequency(const uint32_t frequencyHz); - -/** -* @brief Sets the transmitter power output level, and configures the transmitter pin -* @param newPowerLevel Transmitter power level in dBm (-18 to +20dBm) -* @return True power level adjusted -*/ -LOCAL bool RFM69_setTxPowerLevel(rfm69_powerlevel_t newPowerLevel); - -/** -* @brief Reports the transmitter power output level in dBm -* @return power level -*/ -LOCAL rfm69_powerlevel_t RFM69_getTxPowerLevel(void); - -/** -* @brief Reports the transmitter power output level in percents -* @return power level -*/ -LOCAL uint8_t RFM69_getTxPowerPercent(void); - -/** -* @brief Sets the radio into low-power sleep mode -* @return true if sleep mode was successfully entered -*/ -LOCAL bool RFM69_sleep(void); - -/** -* @brief Sets the radio to standby mode -* @return true if standby mode was successfully entered -*/ -LOCAL bool RFM69_standBy(void); - -/** -* @brief Power down radio (HW) -*/ -LOCAL void RFM69_powerDown(void); - -/** -* @brief Power up radio (HW) -*/ -LOCAL void RFM69_powerUp(void); - -/** -* @brief RFM69_sendACK -* @param recipient -* @param sequenceNumber -* @param RSSI (rfm95_RSSI_t) -*/ -LOCAL void RFM69_sendACK(const uint8_t recipient, const rfm69_sequenceNumber_t sequenceNumber, - const rfm69_RSSI_t RSSI); - -/** -* @brief RFM69_sendWithRetry -* @param recipient -* @param buffer -* @param bufferSize -* @param noACK -* @return True if packet successfully sent -*/ -LOCAL bool RFM69_sendWithRetry(const uint8_t recipient, const void *buffer, - const uint8_t bufferSize, - const bool noACK); - -/** -* @brief RFM69_setRadioMode -* @param newRadioMode -* @return True if mode changed -*/ -LOCAL bool RFM69_setRadioMode(const rfm69_radio_mode_t newRadioMode); - -/** -* @brief Low level interrupt handler -*/ -LOCAL void RFM69_interruptHandler(void); - -/** -* @brief RFM69_getSendingRSSI -* @return RSSI Own RSSI as measured at the receiving node of last sent packet (if ACK & ATC enabled) -*/ -LOCAL int16_t RFM69_getSendingRSSI(void); - -/** -* @brief RFM69_getReceivingRSSI -* @return RSSI Signal strength of last received packet -*/ -LOCAL int16_t RFM69_getReceivingRSSI(void); - -/** -* @brief RFM69_executeATC -* @param currentRSSI -* @param targetRSSI -* @return True if power level adjusted -*/ -LOCAL bool RFM69_executeATC(const rfm69_RSSI_t currentRSSI, const rfm69_RSSI_t targetRSSI); - -// TEMP ADDED -/** -* @brief RFM69_setConfiguration Set general radio register configuration TODO temp use setmodemregisters -*/ -LOCAL void RFM69_setConfiguration(void); - -/** -* @brief RFM69_isModeReady -* @return True if Mode Ready is ok, false is timeout -*/ -LOCAL bool RFM69_isModeReady(void); - -/** -* @brief RFM69_sanityCheck detect HW defect, configuration errors or interrupted SPI line -* @return True if radio sanity check passed -*/ -LOCAL bool RFM69_sanityCheck(void); - -/** -* @brief RFM69_encrypt Set encryption mode -* @param key if key is null, encryption is disabled. Key has to be 16 bytes! -*/ -LOCAL void RFM69_encrypt(const char *key); - -/** -* @brief RFM69_setHighPowerRegs -* @param onOff -*/ -LOCAL void RFM69_setHighPowerRegs(const bool onOff); - -/** -* @brief RFM69_readRSSI -* @param forceTrigger -* @return RSSI (internal format) -*/ -LOCAL rfm69_RSSI_t RFM69_readRSSI(const bool forceTrigger = false); - -/** -* @brief RFM69_ATCmode -* @param targetRSSI Target RSSI for transmitter (default -60) -* @param onOff True to enable ATC -*/ -LOCAL void RFM69_ATCmode(const bool onOff, const int16_t targetRSSI = RFM69_TARGET_RSSI_DBM); - -/** -* @brief RFM69_readAllRegs -* Read and display all RFM69 register contents. -* @note define RFM69_REGISTER_DETAIL for register content decoding. -*/ -LOCAL void RFM69_readAllRegs(void); - -#endif - -/** @}*/ diff --git a/lib/MySensors/hal/transport/RFM69/driver/new/RFM69registers_new.h b/lib/MySensors/hal/transport/RFM69/driver/new/RFM69registers_new.h deleted file mode 100644 index ff17ebb5..00000000 --- a/lib/MySensors/hal/transport/RFM69/driver/new/RFM69registers_new.h +++ /dev/null @@ -1,984 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * RFM69 driver refactored for MySensors - * - * Based on : - * - LowPowerLab RFM69 Lib Copyright Felix Rusu (2014), felix@lowpowerlab.com - * - Automatic Transmit Power Control class derived from RFM69 library. - * Discussion and details in this forum post: https://lowpowerlab.com/forum/index.php/topic,688.0.html - * Copyright Thomas Studwell (2014,2015) - * - MySensors generic radio driver implementation Copyright (C) 2017, 2018 Olivier Mauti - * - * Changes by : @tekka, @scalz, @marceloagno - * - * Definitions for Semtech SX1231/H radios: - * https://www.semtech.com/uploads/documents/sx1231.pdf - * https://www.semtech.com/uploads/documents/sx1231h.pdf - */ - -#define RFM69_REG_FIFO 0x00 -#define RFM69_REG_OPMODE 0x01 -#define RFM69_REG_DATAMODUL 0x02 -#define RFM69_REG_BITRATEMSB 0x03 -#define RFM69_REG_BITRATELSB 0x04 -#define RFM69_REG_FDEVMSB 0x05 -#define RFM69_REG_FDEVLSB 0x06 -#define RFM69_REG_FRFMSB 0x07 -#define RFM69_REG_FRFMID 0x08 -#define RFM69_REG_FRFLSB 0x09 -#define RFM69_REG_OSC1 0x0A -#define RFM69_REG_AFCCTRL 0x0B -#define RFM69_REG_LOWBAT 0x0C -#define RFM69_REG_LISTEN1 0x0D -#define RFM69_REG_LISTEN2 0x0E -#define RFM69_REG_LISTEN3 0x0F -#define RFM69_REG_VERSION 0x10 -#define RFM69_REG_PALEVEL 0x11 -#define RFM69_REG_PARAMP 0x12 -#define RFM69_REG_OCP 0x13 -#define RFM69_REG_AGCREF 0x14 // not present on RFM69/SX1231 -#define RFM69_REG_AGCTHRESH1 0x15 // not present on RFM69/SX1231 -#define RFM69_REG_AGCTHRESH2 0x16 // not present on RFM69/SX1231 -#define RFM69_REG_AGCTHRESH3 0x17 // not present on RFM69/SX1231 -#define RFM69_REG_LNA 0x18 -#define RFM69_REG_RXBW 0x19 -#define RFM69_REG_AFCBW 0x1A -#define RFM69_REG_OOKPEAK 0x1B -#define RFM69_REG_OOKAVG 0x1C -#define RFM69_REG_OOKFIX 0x1D -#define RFM69_REG_AFCFEI 0x1E -#define RFM69_REG_AFCMSB 0x1F -#define RFM69_REG_AFCLSB 0x20 -#define RFM69_REG_FEIMSB 0x21 -#define RFM69_REG_FEILSB 0x22 -#define RFM69_REG_RSSICONFIG 0x23 -#define RFM69_REG_RSSIVALUE 0x24 -#define RFM69_REG_DIOMAPPING1 0x25 -#define RFM69_REG_DIOMAPPING2 0x26 -#define RFM69_REG_IRQFLAGS1 0x27 -#define RFM69_REG_IRQFLAGS2 0x28 -#define RFM69_REG_RSSITHRESH 0x29 -#define RFM69_REG_RXTIMEOUT1 0x2A -#define RFM69_REG_RXTIMEOUT2 0x2B -#define RFM69_REG_PREAMBLEMSB 0x2C -#define RFM69_REG_PREAMBLELSB 0x2D -#define RFM69_REG_SYNCCONFIG 0x2E -#define RFM69_REG_SYNCVALUE1 0x2F -#define RFM69_REG_SYNCVALUE2 0x30 -#define RFM69_REG_SYNCVALUE3 0x31 -#define RFM69_REG_SYNCVALUE4 0x32 -#define RFM69_REG_SYNCVALUE5 0x33 -#define RFM69_REG_SYNCVALUE6 0x34 -#define RFM69_REG_SYNCVALUE7 0x35 -#define RFM69_REG_SYNCVALUE8 0x36 -#define RFM69_REG_PACKETCONFIG1 0x37 -#define RFM69_REG_PAYLOADLENGTH 0x38 -#define RFM69_REG_NODEADRS 0x39 -#define RFM69_REG_BROADCASTADRS 0x3A -#define RFM69_REG_AUTOMODES 0x3B -#define RFM69_REG_FIFOTHRESH 0x3C -#define RFM69_REG_PACKETCONFIG2 0x3D -#define RFM69_REG_AESKEY1 0x3E -#define RFM69_REG_AESKEY2 0x3F -#define RFM69_REG_AESKEY3 0x40 -#define RFM69_REG_AESKEY4 0x41 -#define RFM69_REG_AESKEY5 0x42 -#define RFM69_REG_AESKEY6 0x43 -#define RFM69_REG_AESKEY7 0x44 -#define RFM69_REG_AESKEY8 0x45 -#define RFM69_REG_AESKEY9 0x46 -#define RFM69_REG_AESKEY10 0x47 -#define RFM69_REG_AESKEY11 0x48 -#define RFM69_REG_AESKEY12 0x49 -#define RFM69_REG_AESKEY13 0x4A -#define RFM69_REG_AESKEY14 0x4B -#define RFM69_REG_AESKEY15 0x4C -#define RFM69_REG_AESKEY16 0x4D -#define RFM69_REG_TEMP1 0x4E -#define RFM69_REG_TEMP2 0x4F -#define RFM69_REG_TESTLNA 0x58 -#define RFM69_REG_TESTPA1 0x5A // only present on RFM69HW/SX1231H -#define RFM69_REG_TESTPA2 0x5C // only present on RFM69HW/SX1231H -#define RFM69_REG_TESTDAGC 0x6F - -//****************************************************** -// RF69/SX1231 bit control definition -//****************************************************** - -// RegOpMode -#define RFM69_OPMODE_SEQUENCER_OFF 0x80 -#define RFM69_OPMODE_SEQUENCER_ON 0x00 // Default - -#define RFM69_OPMODE_LISTEN_ON 0x40 -#define RFM69_OPMODE_LISTEN_OFF 0x00 // Default - -#define RFM69_OPMODE_LISTENABORT 0x20 - -#define RFM69_OPMODE_SLEEP 0x00 -#define RFM69_OPMODE_STANDBY 0x04 // Default -#define RFM69_OPMODE_SYNTHESIZER 0x08 -#define RFM69_OPMODE_TRANSMITTER 0x0C -#define RFM69_OPMODE_RECEIVER 0x10 - - -// RegDataModul -#define RFM69_DATAMODUL_DATAMODE_PACKET 0x00 // Default -#define RFM69_DATAMODUL_DATAMODE_CONTINUOUS 0x40 -#define RFM69_DATAMODUL_DATAMODE_CONTINUOUSNOBSYNC 0x60 - -#define RFM69_DATAMODUL_MODULATIONTYPE_FSK 0x00 // Default -#define RFM69_DATAMODUL_MODULATIONTYPE_OOK 0x08 - -#define RFM69_DATAMODUL_MODULATIONSHAPING_00 0x00 // Default -#define RFM69_DATAMODUL_MODULATIONSHAPING_01 0x01 -#define RFM69_DATAMODUL_MODULATIONSHAPING_10 0x02 -#define RFM69_DATAMODUL_MODULATIONSHAPING_11 0x03 - -// RegBitRate (bits/sec) example bit rates -#define RFM69_BITRATEMSB_1200 0x68 -#define RFM69_BITRATELSB_1200 0x2B -#define RFM69_BITRATEMSB_2000 0x3e -#define RFM69_BITRATELSB_2000 0x80 -#define RFM69_BITRATEMSB_2400 0x34 -#define RFM69_BITRATELSB_2400 0x15 -#define RFM69_BITRATEMSB_4800 0x1A // Default -#define RFM69_BITRATELSB_4800 0x0B // Default -#define RFM69_BITRATEMSB_9600 0x0D -#define RFM69_BITRATELSB_9600 0x05 -#define RFM69_BITRATEMSB_12500 0x0A -#define RFM69_BITRATELSB_12500 0x00 -#define RFM69_BITRATEMSB_19200 0x06 -#define RFM69_BITRATELSB_19200 0x83 -#define RFM69_BITRATEMSB_25000 0x05 -#define RFM69_BITRATELSB_25000 0x00 -#define RFM69_BITRATEMSB_32768 0x03 -#define RFM69_BITRATELSB_32768 0xD1 -#define RFM69_BITRATEMSB_38400 0x03 -#define RFM69_BITRATELSB_38400 0x41 -#define RFM69_BITRATEMSB_50000 0x02 -#define RFM69_BITRATELSB_50000 0x80 -#define RFM69_BITRATEMSB_55555 0x02 -#define RFM69_BITRATELSB_55555 0x40 -#define RFM69_BITRATEMSB_57600 0x02 -#define RFM69_BITRATELSB_57600 0x2C -#define RFM69_BITRATEMSB_76800 0x01 -#define RFM69_BITRATELSB_76800 0xA1 -#define RFM69_BITRATEMSB_100000 0x01 -#define RFM69_BITRATELSB_100000 0x40 -#define RFM69_BITRATEMSB_115200 0x01 -#define RFM69_BITRATELSB_115200 0x16 -#define RFM69_BITRATEMSB_125000 0x01 -#define RFM69_BITRATELSB_125000 0x00 -#define RFM69_BITRATEMSB_150000 0x00 -#define RFM69_BITRATELSB_150000 0xD5 -#define RFM69_BITRATEMSB_153600 0x00 -#define RFM69_BITRATELSB_153600 0xD0 -#define RFM69_BITRATEMSB_200000 0x00 -#define RFM69_BITRATELSB_200000 0xA0 -#define RFM69_BITRATEMSB_250000 0x00 -#define RFM69_BITRATELSB_250000 0x80 -#define RFM69_BITRATEMSB_300000 0x00 -#define RFM69_BITRATELSB_300000 0x6B - -// RegFdev - frequency deviation (Hz) -#define RFM69_FDEVMSB_2000 0x00 -#define RFM69_FDEVLSB_2000 0x21 -#define RFM69_FDEVMSB_4800 0x00 -#define RFM69_FDEVLSB_4800 0x4f -#define RFM69_FDEVMSB_5000 0x00 // Default -#define RFM69_FDEVLSB_5000 0x52 // Default -#define RFM69_FDEVMSB_7500 0x00 -#define RFM69_FDEVLSB_7500 0x7B -#define RFM69_FDEVMSB_9600 0x00 -#define RFM69_FDEVLSB_9600 0x9d -#define RFM69_FDEVMSB_10000 0x00 -#define RFM69_FDEVLSB_10000 0xA4 -#define RFM69_FDEVMSB_15000 0x00 -#define RFM69_FDEVLSB_15000 0xF6 -#define RFM69_FDEVMSB_19200 0x01 -#define RFM69_FDEVLSB_19200 0x3b -#define RFM69_FDEVMSB_20000 0x01 -#define RFM69_FDEVLSB_20000 0x48 -#define RFM69_FDEVMSB_25000 0x01 -#define RFM69_FDEVLSB_25000 0x9A -#define RFM69_FDEVMSB_30000 0x01 -#define RFM69_FDEVLSB_30000 0xEC -#define RFM69_FDEVMSB_35000 0x02 -#define RFM69_FDEVLSB_35000 0x3D -#define RFM69_FDEVMSB_38400 0x02 -#define RFM69_FDEVLSB_38400 0x75 -#define RFM69_FDEVMSB_40000 0x02 -#define RFM69_FDEVLSB_40000 0x8F -#define RFM69_FDEVMSB_45000 0x02 -#define RFM69_FDEVLSB_45000 0xE1 -#define RFM69_FDEVMSB_50000 0x03 -#define RFM69_FDEVLSB_50000 0x33 -#define RFM69_FDEVMSB_55000 0x03 -#define RFM69_FDEVLSB_55000 0x85 -#define RFM69_FDEVMSB_60000 0x03 -#define RFM69_FDEVLSB_60000 0xD7 -#define RFM69_FDEVMSB_65000 0x04 -#define RFM69_FDEVLSB_65000 0x29 -#define RFM69_FDEVMSB_70000 0x04 -#define RFM69_FDEVLSB_70000 0x7B -#define RFM69_FDEVMSB_75000 0x04 -#define RFM69_FDEVLSB_75000 0xCD -#define RFM69_FDEVMSB_76800 0x04 -#define RFM69_FDEVLSB_76800 0xea -#define RFM69_FDEVMSB_80000 0x05 -#define RFM69_FDEVLSB_80000 0x1F -#define RFM69_FDEVMSB_85000 0x05 -#define RFM69_FDEVLSB_85000 0x71 -#define RFM69_FDEVMSB_90000 0x05 -#define RFM69_FDEVLSB_90000 0xC3 -#define RFM69_FDEVMSB_95000 0x06 -#define RFM69_FDEVLSB_95000 0x14 -#define RFM69_FDEVMSB_100000 0x06 -#define RFM69_FDEVLSB_100000 0x66 -#define RFM69_FDEVMSB_110000 0x07 -#define RFM69_FDEVLSB_110000 0x0A -#define RFM69_FDEVMSB_120000 0x07 -#define RFM69_FDEVLSB_120000 0xAE -#define RFM69_FDEVMSB_125000 0x08 -#define RFM69_FDEVLSB_125000 0x00 -#define RFM69_FDEVMSB_130000 0x08 -#define RFM69_FDEVLSB_130000 0x52 -#define RFM69_FDEVMSB_140000 0x08 -#define RFM69_FDEVLSB_140000 0xF6 -#define RFM69_FDEVMSB_150000 0x09 -#define RFM69_FDEVLSB_150000 0x9A -#define RFM69_FDEVMSB_160000 0x0A -#define RFM69_FDEVLSB_160000 0x3D -#define RFM69_FDEVMSB_170000 0x0A -#define RFM69_FDEVLSB_170000 0xE1 -#define RFM69_FDEVMSB_180000 0x0B -#define RFM69_FDEVLSB_180000 0x85 -#define RFM69_FDEVMSB_190000 0x0C -#define RFM69_FDEVLSB_190000 0x29 -#define RFM69_FDEVMSB_200000 0x0C -#define RFM69_FDEVLSB_200000 0xCD -#define RFM69_FDEVMSB_210000 0x0D -#define RFM69_FDEVLSB_210000 0x71 -#define RFM69_FDEVMSB_220000 0x0E -#define RFM69_FDEVLSB_220000 0x14 -#define RFM69_FDEVMSB_230000 0x0E -#define RFM69_FDEVLSB_230000 0xB8 -#define RFM69_FDEVMSB_240000 0x0F -#define RFM69_FDEVLSB_240000 0x5C -#define RFM69_FDEVMSB_250000 0x10 -#define RFM69_FDEVLSB_250000 0x00 -#define RFM69_FDEVMSB_260000 0x10 -#define RFM69_FDEVLSB_260000 0xA4 -#define RFM69_FDEVMSB_270000 0x11 -#define RFM69_FDEVLSB_270000 0x48 -#define RFM69_FDEVMSB_280000 0x11 -#define RFM69_FDEVLSB_280000 0xEC -#define RFM69_FDEVMSB_290000 0x12 -#define RFM69_FDEVLSB_290000 0x8F -#define RFM69_FDEVMSB_300000 0x13 -#define RFM69_FDEVLSB_300000 0x33 - -#define RFM69_NOP 0x00 - -// RegOsc1 -#define RFM69_OSC1_RCCAL_START 0x80 -#define RFM69_OSC1_RCCAL_DONE 0x40 - - -// RegAfcCtrl -#define RFM69_AFCCTRL_LOWBETA_OFF 0x00 // Default -#define RFM69_AFCCTRL_LOWBETA_ON 0x20 - - -// RegLowBat -#define RFM69_LOWBAT_MONITOR 0x10 -#define RFM69_LOWBAT_ON 0x08 -#define RFM69_LOWBAT_OFF 0x00 // Default - -#define RFM69_LOWBAT_TRIM_1695 0x00 -#define RFM69_LOWBAT_TRIM_1764 0x01 -#define RFM69_LOWBAT_TRIM_1835 0x02 // Default -#define RFM69_LOWBAT_TRIM_1905 0x03 -#define RFM69_LOWBAT_TRIM_1976 0x04 -#define RFM69_LOWBAT_TRIM_2045 0x05 -#define RFM69_LOWBAT_TRIM_2116 0x06 -#define RFM69_LOWBAT_TRIM_2185 0x07 - - -// RegListen1 -#define RFM69_LISTEN1_RESOL_64 0x50 -#define RFM69_LISTEN1_RESOL_4100 0xA0 // Default -#define RFM69_LISTEN1_RESOL_262000 0xF0 - -#define RFM69_LISTEN1_RESOL_IDLE_64 0x40 -#define RFM69_LISTEN1_RESOL_IDLE_4100 0x80 // Default -#define RFM69_LISTEN1_RESOL_IDLE_262000 0xC0 - -#define RFM69_LISTEN1_RESOL_RX_64 0x10 -#define RFM69_LISTEN1_RESOL_RX_4100 0x20 // Default -#define RFM69_LISTEN1_RESOL_RX_262000 0x30 - -#define RFM69_LISTEN1_CRITERIA_RSSI 0x00 // Default -#define RFM69_LISTEN1_CRITERIA_RSSIANDSYNC 0x08 - -#define RFM69_LISTEN1_END_00 0x00 -#define RFM69_LISTEN1_END_01 0x02 // Default -#define RFM69_LISTEN1_END_10 0x04 - - -// RegListen2 -#define RFM69_LISTEN2_COEFIDLE_VALUE 0xF5 // Default - - -// RegListen3 -#define RFM69_LISTEN3_COEFRX_VALUE 0x20 // Default - - -// RegVersion -#define RFM69_VERSION_VER 0x24 // Default - - -// RegPaLevel -#define RFM69_PALEVEL_PA0_ON 0x80 // Default -#define RFM69_PALEVEL_PA0_OFF 0x00 -#define RFM69_PALEVEL_PA1_ON 0x40 -#define RFM69_PALEVEL_PA1_OFF 0x00 // Default -#define RFM69_PALEVEL_PA2_ON 0x20 -#define RFM69_PALEVEL_PA2_OFF 0x00 // Default - -#define RFM69_PALEVEL_OUTPUTPOWER_00000 0x00 -#define RFM69_PALEVEL_OUTPUTPOWER_00001 0x01 -#define RFM69_PALEVEL_OUTPUTPOWER_00010 0x02 -#define RFM69_PALEVEL_OUTPUTPOWER_00011 0x03 -#define RFM69_PALEVEL_OUTPUTPOWER_00100 0x04 -#define RFM69_PALEVEL_OUTPUTPOWER_00101 0x05 -#define RFM69_PALEVEL_OUTPUTPOWER_00110 0x06 -#define RFM69_PALEVEL_OUTPUTPOWER_00111 0x07 -#define RFM69_PALEVEL_OUTPUTPOWER_01000 0x08 -#define RFM69_PALEVEL_OUTPUTPOWER_01001 0x09 -#define RFM69_PALEVEL_OUTPUTPOWER_01010 0x0A -#define RFM69_PALEVEL_OUTPUTPOWER_01011 0x0B -#define RFM69_PALEVEL_OUTPUTPOWER_01100 0x0C -#define RFM69_PALEVEL_OUTPUTPOWER_01101 0x0D -#define RFM69_PALEVEL_OUTPUTPOWER_01110 0x0E -#define RFM69_PALEVEL_OUTPUTPOWER_01111 0x0F -#define RFM69_PALEVEL_OUTPUTPOWER_10000 0x10 -#define RFM69_PALEVEL_OUTPUTPOWER_10001 0x11 -#define RFM69_PALEVEL_OUTPUTPOWER_10010 0x12 -#define RFM69_PALEVEL_OUTPUTPOWER_10011 0x13 -#define RFM69_PALEVEL_OUTPUTPOWER_10100 0x14 -#define RFM69_PALEVEL_OUTPUTPOWER_10101 0x15 -#define RFM69_PALEVEL_OUTPUTPOWER_10110 0x16 -#define RFM69_PALEVEL_OUTPUTPOWER_10111 0x17 -#define RFM69_PALEVEL_OUTPUTPOWER_11000 0x18 -#define RFM69_PALEVEL_OUTPUTPOWER_11001 0x19 -#define RFM69_PALEVEL_OUTPUTPOWER_11010 0x1A -#define RFM69_PALEVEL_OUTPUTPOWER_11011 0x1B -#define RFM69_PALEVEL_OUTPUTPOWER_11100 0x1C -#define RFM69_PALEVEL_OUTPUTPOWER_11101 0x1D -#define RFM69_PALEVEL_OUTPUTPOWER_11110 0x1E -#define RFM69_PALEVEL_OUTPUTPOWER_11111 0x1F // Default - - -// RegPaRamp -#define RFM69_PARAMP_3400 0x00 -#define RFM69_PARAMP_2000 0x01 -#define RFM69_PARAMP_1000 0x02 -#define RFM69_PARAMP_500 0x03 -#define RFM69_PARAMP_250 0x04 -#define RFM69_PARAMP_125 0x05 -#define RFM69_PARAMP_100 0x06 -#define RFM69_PARAMP_62 0x07 -#define RFM69_PARAMP_50 0x08 -#define RFM69_PARAMP_40 0x09 // Default -#define RFM69_PARAMP_31 0x0A -#define RFM69_PARAMP_25 0x0B -#define RFM69_PARAMP_20 0x0C -#define RFM69_PARAMP_15 0x0D -#define RFM69_PARAMP_12 0x0E -#define RFM69_PARAMP_10 0x0F - - -// RegOcp -#define RFM69_OCP_OFF 0x0F -#define RFM69_OCP_ON 0x1A // Default - -#define RFM69_OCP_TRIM_45 0x00 -#define RFM69_OCP_TRIM_50 0x01 -#define RFM69_OCP_TRIM_55 0x02 -#define RFM69_OCP_TRIM_60 0x03 -#define RFM69_OCP_TRIM_65 0x04 -#define RFM69_OCP_TRIM_70 0x05 -#define RFM69_OCP_TRIM_75 0x06 -#define RFM69_OCP_TRIM_80 0x07 -#define RFM69_OCP_TRIM_85 0x08 -#define RFM69_OCP_TRIM_90 0x09 -#define RFM69_OCP_TRIM_95 0x0A // Default -#define RFM69_OCP_TRIM_100 0x0B -#define RFM69_OCP_TRIM_105 0x0C -#define RFM69_OCP_TRIM_110 0x0D -#define RFM69_OCP_TRIM_115 0x0E -#define RFM69_OCP_TRIM_120 0x0F - - -// RegAgcRef - not present on RFM69/SX1231 -#define RFM69_AGCREF_AUTO_ON 0x40 // Default -#define RFM69_AGCREF_AUTO_OFF 0x00 - -#define RFM69_AGCREF_LEVEL_MINUS80 0x00 // Default -#define RFM69_AGCREF_LEVEL_MINUS81 0x01 -#define RFM69_AGCREF_LEVEL_MINUS82 0x02 -#define RFM69_AGCREF_LEVEL_MINUS83 0x03 -#define RFM69_AGCREF_LEVEL_MINUS84 0x04 -#define RFM69_AGCREF_LEVEL_MINUS85 0x05 -#define RFM69_AGCREF_LEVEL_MINUS86 0x06 -#define RFM69_AGCREF_LEVEL_MINUS87 0x07 -#define RFM69_AGCREF_LEVEL_MINUS88 0x08 -#define RFM69_AGCREF_LEVEL_MINUS89 0x09 -#define RFM69_AGCREF_LEVEL_MINUS90 0x0A -#define RFM69_AGCREF_LEVEL_MINUS91 0x0B -#define RFM69_AGCREF_LEVEL_MINUS92 0x0C -#define RFM69_AGCREF_LEVEL_MINUS93 0x0D -#define RFM69_AGCREF_LEVEL_MINUS94 0x0E -#define RFM69_AGCREF_LEVEL_MINUS95 0x0F -#define RFM69_AGCREF_LEVEL_MINUS96 0x10 -#define RFM69_AGCREF_LEVEL_MINUS97 0x11 -#define RFM69_AGCREF_LEVEL_MINUS98 0x12 -#define RFM69_AGCREF_LEVEL_MINUS99 0x13 -#define RFM69_AGCREF_LEVEL_MINUS100 0x14 -#define RFM69_AGCREF_LEVEL_MINUS101 0x15 -#define RFM69_AGCREF_LEVEL_MINUS102 0x16 -#define RFM69_AGCREF_LEVEL_MINUS103 0x17 -#define RFM69_AGCREF_LEVEL_MINUS104 0x18 -#define RFM69_AGCREF_LEVEL_MINUS105 0x19 -#define RFM69_AGCREF_LEVEL_MINUS106 0x1A -#define RFM69_AGCREF_LEVEL_MINUS107 0x1B -#define RFM69_AGCREF_LEVEL_MINUS108 0x1C -#define RFM69_AGCREF_LEVEL_MINUS109 0x1D -#define RFM69_AGCREF_LEVEL_MINUS110 0x1E -#define RFM69_AGCREF_LEVEL_MINUS111 0x1F -#define RFM69_AGCREF_LEVEL_MINUS112 0x20 -#define RFM69_AGCREF_LEVEL_MINUS113 0x21 -#define RFM69_AGCREF_LEVEL_MINUS114 0x22 -#define RFM69_AGCREF_LEVEL_MINUS115 0x23 -#define RFM69_AGCREF_LEVEL_MINUS116 0x24 -#define RFM69_AGCREF_LEVEL_MINUS117 0x25 -#define RFM69_AGCREF_LEVEL_MINUS118 0x26 -#define RFM69_AGCREF_LEVEL_MINUS119 0x27 -#define RFM69_AGCREF_LEVEL_MINUS120 0x28 -#define RFM69_AGCREF_LEVEL_MINUS121 0x29 -#define RFM69_AGCREF_LEVEL_MINUS122 0x2A -#define RFM69_AGCREF_LEVEL_MINUS123 0x2B -#define RFM69_AGCREF_LEVEL_MINUS124 0x2C -#define RFM69_AGCREF_LEVEL_MINUS125 0x2D -#define RFM69_AGCREF_LEVEL_MINUS126 0x2E -#define RFM69_AGCREF_LEVEL_MINUS127 0x2F -#define RFM69_AGCREF_LEVEL_MINUS128 0x30 -#define RFM69_AGCREF_LEVEL_MINUS129 0x31 -#define RFM69_AGCREF_LEVEL_MINUS130 0x32 -#define RFM69_AGCREF_LEVEL_MINUS131 0x33 -#define RFM69_AGCREF_LEVEL_MINUS132 0x34 -#define RFM69_AGCREF_LEVEL_MINUS133 0x35 -#define RFM69_AGCREF_LEVEL_MINUS134 0x36 -#define RFM69_AGCREF_LEVEL_MINUS135 0x37 -#define RFM69_AGCREF_LEVEL_MINUS136 0x38 -#define RFM69_AGCREF_LEVEL_MINUS137 0x39 -#define RFM69_AGCREF_LEVEL_MINUS138 0x3A -#define RFM69_AGCREF_LEVEL_MINUS139 0x3B -#define RFM69_AGCREF_LEVEL_MINUS140 0x3C -#define RFM69_AGCREF_LEVEL_MINUS141 0x3D -#define RFM69_AGCREF_LEVEL_MINUS142 0x3E -#define RFM69_AGCREF_LEVEL_MINUS143 0x3F - - -// RegAgcThresh1 - not present on RFM69/SX1231 -#define RFM69_AGCTHRESH1_SNRMARGIN_000 0x00 -#define RFM69_AGCTHRESH1_SNRMARGIN_001 0x20 -#define RFM69_AGCTHRESH1_SNRMARGIN_010 0x40 -#define RFM69_AGCTHRESH1_SNRMARGIN_011 0x60 -#define RFM69_AGCTHRESH1_SNRMARGIN_100 0x80 -#define RFM69_AGCTHRESH1_SNRMARGIN_101 0xA0 // Default -#define RFM69_AGCTHRESH1_SNRMARGIN_110 0xC0 -#define RFM69_AGCTHRESH1_SNRMARGIN_111 0xE0 - -#define RFM69_AGCTHRESH1_STEP1_0 0x00 -#define RFM69_AGCTHRESH1_STEP1_1 0x01 -#define RFM69_AGCTHRESH1_STEP1_2 0x02 -#define RFM69_AGCTHRESH1_STEP1_3 0x03 -#define RFM69_AGCTHRESH1_STEP1_4 0x04 -#define RFM69_AGCTHRESH1_STEP1_5 0x05 -#define RFM69_AGCTHRESH1_STEP1_6 0x06 -#define RFM69_AGCTHRESH1_STEP1_7 0x07 -#define RFM69_AGCTHRESH1_STEP1_8 0x08 -#define RFM69_AGCTHRESH1_STEP1_9 0x09 -#define RFM69_AGCTHRESH1_STEP1_10 0x0A -#define RFM69_AGCTHRESH1_STEP1_11 0x0B -#define RFM69_AGCTHRESH1_STEP1_12 0x0C -#define RFM69_AGCTHRESH1_STEP1_13 0x0D -#define RFM69_AGCTHRESH1_STEP1_14 0x0E -#define RFM69_AGCTHRESH1_STEP1_15 0x0F -#define RFM69_AGCTHRESH1_STEP1_16 0x10 // Default -#define RFM69_AGCTHRESH1_STEP1_17 0x11 -#define RFM69_AGCTHRESH1_STEP1_18 0x12 -#define RFM69_AGCTHRESH1_STEP1_19 0x13 -#define RFM69_AGCTHRESH1_STEP1_20 0x14 -#define RFM69_AGCTHRESH1_STEP1_21 0x15 -#define RFM69_AGCTHRESH1_STEP1_22 0x16 -#define RFM69_AGCTHRESH1_STEP1_23 0x17 -#define RFM69_AGCTHRESH1_STEP1_24 0x18 -#define RFM69_AGCTHRESH1_STEP1_25 0x19 -#define RFM69_AGCTHRESH1_STEP1_26 0x1A -#define RFM69_AGCTHRESH1_STEP1_27 0x1B -#define RFM69_AGCTHRESH1_STEP1_28 0x1C -#define RFM69_AGCTHRESH1_STEP1_29 0x1D -#define RFM69_AGCTHRESH1_STEP1_30 0x1E -#define RFM69_AGCTHRESH1_STEP1_31 0x1F - - -// RegAgcThresh2 - not present on RFM69/SX1231 -#define RFM69_AGCTHRESH2_STEP2_0 0x00 -#define RFM69_AGCTHRESH2_STEP2_1 0x10 -#define RFM69_AGCTHRESH2_STEP2_2 0x20 -#define RFM69_AGCTHRESH2_STEP2_3 0x30 // XXX wrong -- Default -#define RFM69_AGCTHRESH2_STEP2_4 0x40 -#define RFM69_AGCTHRESH2_STEP2_5 0x50 -#define RFM69_AGCTHRESH2_STEP2_6 0x60 -#define RFM69_AGCTHRESH2_STEP2_7 0x70 // default -#define RFM69_AGCTHRESH2_STEP2_8 0x80 -#define RFM69_AGCTHRESH2_STEP2_9 0x90 -#define RFM69_AGCTHRESH2_STEP2_10 0xA0 -#define RFM69_AGCTHRESH2_STEP2_11 0xB0 -#define RFM69_AGCTHRESH2_STEP2_12 0xC0 -#define RFM69_AGCTHRESH2_STEP2_13 0xD0 -#define RFM69_AGCTHRESH2_STEP2_14 0xE0 -#define RFM69_AGCTHRESH2_STEP2_15 0xF0 - -#define RFM69_AGCTHRESH2_STEP3_0 0x00 -#define RFM69_AGCTHRESH2_STEP3_1 0x01 -#define RFM69_AGCTHRESH2_STEP3_2 0x02 -#define RFM69_AGCTHRESH2_STEP3_3 0x03 -#define RFM69_AGCTHRESH2_STEP3_4 0x04 -#define RFM69_AGCTHRESH2_STEP3_5 0x05 -#define RFM69_AGCTHRESH2_STEP3_6 0x06 -#define RFM69_AGCTHRESH2_STEP3_7 0x07 -#define RFM69_AGCTHRESH2_STEP3_8 0x08 -#define RFM69_AGCTHRESH2_STEP3_9 0x09 -#define RFM69_AGCTHRESH2_STEP3_10 0x0A -#define RFM69_AGCTHRESH2_STEP3_11 0x0B // Default -#define RFM69_AGCTHRESH2_STEP3_12 0x0C -#define RFM69_AGCTHRESH2_STEP3_13 0x0D -#define RFM69_AGCTHRESH2_STEP3_14 0x0E -#define RFM69_AGCTHRESH2_STEP3_15 0x0F - - -// RegAgcThresh3 - not present on RFM69/SX1231 -#define RFM69_AGCTHRESH3_STEP4_0 0x00 -#define RFM69_AGCTHRESH3_STEP4_1 0x10 -#define RFM69_AGCTHRESH3_STEP4_2 0x20 -#define RFM69_AGCTHRESH3_STEP4_3 0x30 -#define RFM69_AGCTHRESH3_STEP4_4 0x40 -#define RFM69_AGCTHRESH3_STEP4_5 0x50 -#define RFM69_AGCTHRESH3_STEP4_6 0x60 -#define RFM69_AGCTHRESH3_STEP4_7 0x70 -#define RFM69_AGCTHRESH3_STEP4_8 0x80 -#define RFM69_AGCTHRESH3_STEP4_9 0x90 // Default -#define RFM69_AGCTHRESH3_STEP4_10 0xA0 -#define RFM69_AGCTHRESH3_STEP4_11 0xB0 -#define RFM69_AGCTHRESH3_STEP4_12 0xC0 -#define RFM69_AGCTHRESH3_STEP4_13 0xD0 -#define RFM69_AGCTHRESH3_STEP4_14 0xE0 -#define RFM69_AGCTHRESH3_STEP4_15 0xF0 - -#define RFM69_AGCTHRESH3_STEP5_0 0x00 -#define RFM69_AGCTHRESH3_STEP5_1 0x01 -#define RFM69_AGCTHRESH3_STEP5_2 0x02 -#define RFM69_AGCTHRESH3_STEP5_3 0x03 -#define RFM69_AGCTHRESH3_STEP5_4 0x04 -#define RFM69_AGCTHRESH3_STEP5_5 0x05 -#define RFM69_AGCTHRESH3_STEP5_6 0x06 -#define RFM69_AGCTHRESH3_STEP5_7 0x07 -#define RFM69_AGCTHRES33_STEP5_8 0x08 -#define RFM69_AGCTHRESH3_STEP5_9 0x09 -#define RFM69_AGCTHRESH3_STEP5_10 0x0A -#define RFM69_AGCTHRESH3_STEP5_11 0x0B // Default -#define RFM69_AGCTHRESH3_STEP5_12 0x0C -#define RFM69_AGCTHRESH3_STEP5_13 0x0D -#define RFM69_AGCTHRESH3_STEP5_14 0x0E -#define RFM69_AGCTHRESH3_STEP5_15 0x0F - - -// RegLna -#define RFM69_LNA_ZIN_50 0x00 // Reset value -#define RFM69_LNA_ZIN_200 0x80 // Recommended default - -#define RFM69_LNA_LOWPOWER_OFF 0x00 // Default -#define RFM69_LNA_LOWPOWER_ON 0x40 - -#define RFM69_LNA_CURRENTGAIN 0x08 - -#define RFM69_LNA_GAINSELECT_AUTO 0x00 // Default -#define RFM69_LNA_GAINSELECT_MAX 0x01 -#define RFM69_LNA_GAINSELECT_MAXMINUS6 0x02 -#define RFM69_LNA_GAINSELECT_MAXMINUS12 0x03 -#define RFM69_LNA_GAINSELECT_MAXMINUS24 0x04 -#define RFM69_LNA_GAINSELECT_MAXMINUS36 0x05 -#define RFM69_LNA_GAINSELECT_MAXMINUS48 0x06 - - -// RegRxBw -#define RFM69_RXBW_DCCFREQ_000 0x00 -#define RFM69_RXBW_DCCFREQ_001 0x20 -#define RFM69_RXBW_DCCFREQ_010 0x40 // Recommended default -#define RFM69_RXBW_DCCFREQ_011 0x60 -#define RFM69_RXBW_DCCFREQ_100 0x80 // Reset value -#define RFM69_RXBW_DCCFREQ_101 0xA0 -#define RFM69_RXBW_DCCFREQ_110 0xC0 -#define RFM69_RXBW_DCCFREQ_111 0xE0 - -#define RFM69_RXBW_MANT_16 0x00 // Reset value -#define RFM69_RXBW_MANT_20 0x08 -#define RFM69_RXBW_MANT_24 0x10 // Recommended default - -#define RFM69_RXBW_EXP_0 0x00 -#define RFM69_RXBW_EXP_1 0x01 -#define RFM69_RXBW_EXP_2 0x02 -#define RFM69_RXBW_EXP_3 0x03 -#define RFM69_RXBW_EXP_4 0x04 -#define RFM69_RXBW_EXP_5 0x05 // Recommended default -#define RFM69_RXBW_EXP_6 0x06 // Reset value -#define RFM69_RXBW_EXP_7 0x07 - - -// RegAfcBw -#define RFM69_AFCBW_DCCFREQAFC_000 0x00 -#define RFM69_AFCBW_DCCFREQAFC_001 0x20 -#define RFM69_AFCBW_DCCFREQAFC_010 0x40 -#define RFM69_AFCBW_DCCFREQAFC_011 0x60 -#define RFM69_AFCBW_DCCFREQAFC_100 0x80 // Default -#define RFM69_AFCBW_DCCFREQAFC_101 0xA0 -#define RFM69_AFCBW_DCCFREQAFC_110 0xC0 -#define RFM69_AFCBW_DCCFREQAFC_111 0xE0 - -#define RFM69_AFCBW_MANTAFC_16 0x00 -#define RFM69_AFCBW_MANTAFC_20 0x08 // Default -#define RFM69_AFCBW_MANTAFC_24 0x10 - -#define RFM69_AFCBW_EXPAFC_0 0x00 -#define RFM69_AFCBW_EXPAFC_1 0x01 -#define RFM69_AFCBW_EXPAFC_2 0x02 // Reset value -#define RFM69_AFCBW_EXPAFC_3 0x03 // Recommended default -#define RFM69_AFCBW_EXPAFC_4 0x04 -#define RFM69_AFCBW_EXPAFC_5 0x05 -#define RFM69_AFCBW_EXPAFC_6 0x06 -#define RFM69_AFCBW_EXPAFC_7 0x07 - - -// RegOokPeak -#define RFM69_OOKPEAK_THRESHTYPE_FIXED 0x00 -#define RFM69_OOKPEAK_THRESHTYPE_PEAK 0x40 // Default -#define RFM69_OOKPEAK_THRESHTYPE_AVERAGE 0x80 - -#define RFM69_OOKPEAK_PEAKTHRESHSTEP_000 0x00 // Default -#define RFM69_OOKPEAK_PEAKTHRESHSTEP_001 0x08 -#define RFM69_OOKPEAK_PEAKTHRESHSTEP_010 0x10 -#define RFM69_OOKPEAK_PEAKTHRESHSTEP_011 0x18 -#define RFM69_OOKPEAK_PEAKTHRESHSTEP_100 0x20 -#define RFM69_OOKPEAK_PEAKTHRESHSTEP_101 0x28 -#define RFM69_OOKPEAK_PEAKTHRESHSTEP_110 0x30 -#define RFM69_OOKPEAK_PEAKTHRESHSTEP_111 0x38 - -#define RFM69_OOKPEAK_PEAKTHRESHDEC_000 0x00 // Default -#define RFM69_OOKPEAK_PEAKTHRESHDEC_001 0x01 -#define RFM69_OOKPEAK_PEAKTHRESHDEC_010 0x02 -#define RFM69_OOKPEAK_PEAKTHRESHDEC_011 0x03 -#define RFM69_OOKPEAK_PEAKTHRESHDEC_100 0x04 -#define RFM69_OOKPEAK_PEAKTHRESHDEC_101 0x05 -#define RFM69_OOKPEAK_PEAKTHRESHDEC_110 0x06 -#define RFM69_OOKPEAK_PEAKTHRESHDEC_111 0x07 - - -// RegOokAvg -#define RFM69_OOKAVG_AVERAGETHRESHFILT_00 0x00 -#define RFM69_OOKAVG_AVERAGETHRESHFILT_01 0x40 -#define RFM69_OOKAVG_AVERAGETHRESHFILT_10 0x80 // Default -#define RFM69_OOKAVG_AVERAGETHRESHFILT_11 0xC0 - - -// RegOokFix -#define RFM69_OOKFIX_FIXEDTHRESH_VALUE 0x06 // Default - - -// RegAfcFei -#define RFM69_AFCFEI_FEI_DONE 0x40 -#define RFM69_AFCFEI_FEI_START 0x20 -#define RFM69_AFCFEI_AFC_DONE 0x10 -#define RFM69_AFCFEI_AFCAUTOCLEAR_ON 0x08 -#define RFM69_AFCFEI_AFCAUTOCLEAR_OFF 0x00 // Default - -#define RFM69_AFCFEI_AFCAUTO_ON 0x04 -#define RFM69_AFCFEI_AFCAUTO_OFF 0x00 // Default - -#define RFM69_AFCFEI_AFC_CLEAR 0x02 -#define RFM69_AFCFEI_AFC_START 0x01 - - -// RegRssiConfig -#define RFM69_RSSI_FASTRX_ON 0x08 // not present on RFM69/SX1231 -#define RFM69_RSSI_FASTRX_OFF 0x00 // Default - -#define RFM69_RSSI_DONE 0x02 -#define RFM69_RSSI_START 0x01 - - -// RegDioMapping1 -#define RFM69_DIOMAPPING1_DIO0_00 0x00 // Default -#define RFM69_DIOMAPPING1_DIO0_01 0x40 -#define RFM69_DIOMAPPING1_DIO0_10 0x80 -#define RFM69_DIOMAPPING1_DIO0_11 0xC0 - -#define RFM69_DIOMAPPING1_DIO1_00 0x00 // Default -#define RFM69_DIOMAPPING1_DIO1_01 0x10 -#define RFM69_DIOMAPPING1_DIO1_10 0x20 -#define RFM69_DIOMAPPING1_DIO1_11 0x30 - -#define RFM69_DIOMAPPING1_DIO2_00 0x00 // Default -#define RFM69_DIOMAPPING1_DIO2_01 0x04 -#define RFM69_DIOMAPPING1_DIO2_10 0x08 -#define RFM69_DIOMAPPING1_DIO2_11 0x0C - -#define RFM69_DIOMAPPING1_DIO3_00 0x00 // Default -#define RFM69_DIOMAPPING1_DIO3_01 0x01 -#define RFM69_DIOMAPPING1_DIO3_10 0x02 -#define RFM69_DIOMAPPING1_DIO3_11 0x03 - - -// RegDioMapping2 -#define RFM69_DIOMAPPING2_DIO4_00 0x00 // Default -#define RFM69_DIOMAPPING2_DIO4_01 0x40 -#define RFM69_DIOMAPPING2_DIO4_10 0x80 -#define RFM69_DIOMAPPING2_DIO4_11 0xC0 - -#define RFM69_DIOMAPPING2_DIO5_00 0x00 // Default -#define RFM69_DIOMAPPING2_DIO5_01 0x10 -#define RFM69_DIOMAPPING2_DIO5_10 0x20 -#define RFM69_DIOMAPPING2_DIO5_11 0x30 - -#define RFM69_DIOMAPPING2_CLKOUT_32 0x00 -#define RFM69_DIOMAPPING2_CLKOUT_16 0x01 -#define RFM69_DIOMAPPING2_CLKOUT_8 0x02 -#define RFM69_DIOMAPPING2_CLKOUT_4 0x03 -#define RFM69_DIOMAPPING2_CLKOUT_2 0x04 -#define RFM69_DIOMAPPING2_CLKOUT_1 0x05 // Reset value -#define RFM69_DIOMAPPING2_CLKOUT_RC 0x06 -#define RFM69_DIOMAPPING2_CLKOUT_OFF 0x07 // Recommended default - - -// RegIrqFlags1 -#define RFM69_IRQFLAGS1_MODEREADY 0x80 -#define RFM69_IRQFLAGS1_RXREADY 0x40 -#define RFM69_IRQFLAGS1_TXREADY 0x20 -#define RFM69_IRQFLAGS1_PLLLOCK 0x10 -#define RFM69_IRQFLAGS1_RSSI 0x08 -#define RFM69_IRQFLAGS1_TIMEOUT 0x04 -#define RFM69_IRQFLAGS1_AUTOMODE 0x02 -#define RFM69_IRQFLAGS1_SYNCADDRESSMATCH 0x01 - - -// RegIrqFlags2 -#define RFM69_IRQFLAGS2_FIFOFULL 0x80 -#define RFM69_IRQFLAGS2_FIFONOTEMPTY 0x40 -#define RFM69_IRQFLAGS2_FIFOLEVEL 0x20 -#define RFM69_IRQFLAGS2_FIFOOVERRUN 0x10 -#define RFM69_IRQFLAGS2_PACKETSENT 0x08 -#define RFM69_IRQFLAGS2_PAYLOADREADY 0x04 -#define RFM69_IRQFLAGS2_CRCOK 0x02 -#define RFM69_IRQFLAGS2_LOWBAT 0x01 // not present on RFM69/SX1231 - - -// RegRssiThresh -#define RFM69_RSSITHRESH_VALUE 0xE4 // Default - - -// RegRxTimeout1 -#define RFM69_RXTIMEOUT1_RXSTART_VALUE 0x00 // Default - - -// RegRxTimeout2 -#define RFM69_RXTIMEOUT2_RSSITHRESH_VALUE 0x00 // Default - - -// RegPreamble -#define RFM69_PREAMBLESIZE_MSB_VALUE 0x00 // Default -#define RFM69_PREAMBLESIZE_LSB_VALUE 0x03 // Default - - -// RegSyncConfig -#define RFM69_SYNC_ON 0x80 // Default -#define RFM69_SYNC_OFF 0x00 - -#define RFM69_SYNC_FIFOFILL_AUTO 0x00 // Default -- when sync interrupt occurs -#define RFM69_SYNC_FIFOFILL_MANUAL 0x40 - -#define RFM69_SYNC_SIZE_1 0x00 -#define RFM69_SYNC_SIZE_2 0x08 -#define RFM69_SYNC_SIZE_3 0x10 -#define RFM69_SYNC_SIZE_4 0x18 // Default -#define RFM69_SYNC_SIZE_5 0x20 -#define RFM69_SYNC_SIZE_6 0x28 -#define RFM69_SYNC_SIZE_7 0x30 -#define RFM69_SYNC_SIZE_8 0x38 - -#define RFM69_SYNC_TOL_0 0x00 // Default -#define RFM69_SYNC_TOL_1 0x01 -#define RFM69_SYNC_TOL_2 0x02 -#define RFM69_SYNC_TOL_3 0x03 -#define RFM69_SYNC_TOL_4 0x04 -#define RFM69_SYNC_TOL_5 0x05 -#define RFM69_SYNC_TOL_6 0x06 -#define RFM69_SYNC_TOL_7 0x07 - - -// RegSyncValue1-8 -#define RFM69_SYNC_BYTE1_VALUE 0x00 // Default -#define RFM69_SYNC_BYTE2_VALUE 0x00 // Default -#define RFM69_SYNC_BYTE3_VALUE 0x00 // Default -#define RFM69_SYNC_BYTE4_VALUE 0x00 // Default -#define RFM69_SYNC_BYTE5_VALUE 0x00 // Default -#define RFM69_SYNC_BYTE6_VALUE 0x00 // Default -#define RFM69_SYNC_BYTE7_VALUE 0x00 // Default -#define RFM69_SYNC_BYTE8_VALUE 0x00 // Default - - -// RegPacketConfig1 -#define RFM69_PACKET1_FORMAT_FIXED 0x00 // Default -#define RFM69_PACKET1_FORMAT_VARIABLE 0x80 - -#define RFM69_PACKET1_DCFREE_OFF 0x00 // Default -#define RFM69_PACKET1_DCFREE_MANCHESTER 0x20 -#define RFM69_PACKET1_DCFREE_WHITENING 0x40 - -#define RFM69_PACKET1_CRC_ON 0x10 // Default -#define RFM69_PACKET1_CRC_OFF 0x00 - -#define RFM69_PACKET1_CRCAUTOCLEAR_ON 0x00 // Default -#define RFM69_PACKET1_CRCAUTOCLEAR_OFF 0x08 - -#define RFM69_PACKET1_ADRSFILTERING_OFF 0x00 // Default -#define RFM69_PACKET1_ADRSFILTERING_NODE 0x02 -#define RFM69_PACKET1_ADRSFILTERING_NODEBROADCAST 0x04 - - -// RegPayloadLength -#define RFM69_PAYLOADLENGTH_VALUE 0x40 // Default - - -// RegBroadcastAdrs -#define RFM69_BROADCASTADDRESS_VALUE 0x00 - - -// RegAutoModes -#define RFM69_AUTOMODES_ENTER_OFF 0x00 // Default -#define RFM69_AUTOMODES_ENTER_FIFONOTEMPTY 0x20 -#define RFM69_AUTOMODES_ENTER_FIFOLEVEL 0x40 -#define RFM69_AUTOMODES_ENTER_CRCOK 0x60 -#define RFM69_AUTOMODES_ENTER_PAYLOADREADY 0x80 -#define RFM69_AUTOMODES_ENTER_SYNCADRSMATCH 0xA0 -#define RFM69_AUTOMODES_ENTER_PACKETSENT 0xC0 -#define RFM69_AUTOMODES_ENTER_FIFOEMPTY 0xE0 - -#define RFM69_AUTOMODES_EXIT_OFF 0x00 // Default -#define RFM69_AUTOMODES_EXIT_FIFOEMPTY 0x04 -#define RFM69_AUTOMODES_EXIT_FIFOLEVEL 0x08 -#define RFM69_AUTOMODES_EXIT_CRCOK 0x0C -#define RFM69_AUTOMODES_EXIT_PAYLOADREADY 0x10 -#define RFM69_AUTOMODES_EXIT_SYNCADRSMATCH 0x14 -#define RFM69_AUTOMODES_EXIT_PACKETSENT 0x18 -#define RFM69_AUTOMODES_EXIT_RXTIMEOUT 0x1C - -#define RFM69_AUTOMODES_INTERMEDIATE_SLEEP 0x00 // Default -#define RFM69_AUTOMODES_INTERMEDIATE_STANDBY 0x01 -#define RFM69_AUTOMODES_INTERMEDIATE_RECEIVER 0x02 -#define RFM69_AUTOMODES_INTERMEDIATE_TRANSMITTER 0x03 - - -// RegFifoThresh -#define RFM69_FIFOTHRESH_TXSTART_FIFOTHRESH 0x00 // Reset value -#define RFM69_FIFOTHRESH_TXSTART_FIFONOTEMPTY 0x80 // Recommended default -#define RFM69_FIFOTHRESH_VALUE 0x0F // Default - - -// RegPacketConfig2 -#define RFM69_PACKET2_RXRESTARTDELAY_1BIT 0x00 // Default -#define RFM69_PACKET2_RXRESTARTDELAY_2BITS 0x10 -#define RFM69_PACKET2_RXRESTARTDELAY_4BITS 0x20 -#define RFM69_PACKET2_RXRESTARTDELAY_8BITS 0x30 -#define RFM69_PACKET2_RXRESTARTDELAY_16BITS 0x40 -#define RFM69_PACKET2_RXRESTARTDELAY_32BITS 0x50 -#define RFM69_PACKET2_RXRESTARTDELAY_64BITS 0x60 -#define RFM69_PACKET2_RXRESTARTDELAY_128BITS 0x70 -#define RFM69_PACKET2_RXRESTARTDELAY_256BITS 0x80 -#define RFM69_PACKET2_RXRESTARTDELAY_512BITS 0x90 -#define RFM69_PACKET2_RXRESTARTDELAY_1024BITS 0xA0 -#define RFM69_PACKET2_RXRESTARTDELAY_2048BITS 0xB0 -#define RFM69_PACKET2_RXRESTARTDELAY_NONE 0xC0 -#define RFM69_PACKET2_RXRESTART 0x04 - -#define RFM69_PACKET2_AUTORXRESTART_ON 0x02 // Default -#define RFM69_PACKET2_AUTORXRESTART_OFF 0x00 - -#define RFM69_PACKET2_AES_ON 0x01 -#define RFM69_PACKET2_AES_OFF 0x00 // Default - - -// RegAesKey1-16 -#define RFM69_AESKEY1_VALUE 0x00 // Default -#define RFM69_AESKEY2_VALUE 0x00 // Default -#define RFM69_AESKEY3_VALUE 0x00 // Default -#define RFM69_AESKEY4_VALUE 0x00 // Default -#define RFM69_AESKEY5_VALUE 0x00 // Default -#define RFM69_AESKEY6_VALUE 0x00 // Default -#define RFM69_AESKEY7_VALUE 0x00 // Default -#define RFM69_AESKEY8_VALUE 0x00 // Default -#define RFM69_AESKEY9_VALUE 0x00 // Default -#define RFM69_AESKEY10_VALUE 0x00 // Default -#define RFM69_AESKEY11_VALUE 0x00 // Default -#define RFM69_AESKEY12_VALUE 0x00 // Default -#define RFM69_AESKEY13_VALUE 0x00 // Default -#define RFM69_AESKEY14_VALUE 0x00 // Default -#define RFM69_AESKEY15_VALUE 0x00 // Default -#define RFM69_AESKEY16_VALUE 0x00 // Default - - -// RegTemp1 -#define RFM69_TEMP1_MEAS_START 0x08 -#define RFM69_TEMP1_MEAS_RUNNING 0x04 -// not present on RFM69/SX1231 -#define RFM69_TEMP1_ADCLOWPOWER_ON 0x01 // Default -#define RFM69_TEMP1_ADCLOWPOWER_OFF 0x00 - - -// RegTestLna -#define RFM69_TESTLNA_NORMAL 0x1B -#define RFM69_TESTLNA_HIGH_SENSITIVITY 0x2D - - -// RegTestDagc -#define RFM69_DAGC_NORMAL 0x00 // Reset value -#define RFM69_DAGC_IMPROVED_LOWBETA1 0x20 -#define RFM69_DAGC_IMPROVED_LOWBETA0 0x30 // Recommended default diff --git a/lib/MySensors/hal/transport/RFM69/driver/old/RFM69_old.cpp b/lib/MySensors/hal/transport/RFM69/driver/old/RFM69_old.cpp deleted file mode 100644 index 9d840a3d..00000000 --- a/lib/MySensors/hal/transport/RFM69/driver/old/RFM69_old.cpp +++ /dev/null @@ -1,913 +0,0 @@ -// ********************************************************************************** -// Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech SX1231/1231H -// ********************************************************************************** -// Copyright Felix Rusu (2014), felix@lowpowerlab.com -// http://lowpowerlab.com/ -// ********************************************************************************** -// License -// ********************************************************************************** -// 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 . -// -// Licence can be viewed at -// http://www.gnu.org/licenses/gpl-3.0.txt -// -// Please maintain this license information along with authorship -// and copyright notices in any redistribution of this code -// ********************************************************************************** -#include "RFM69_old.h" -#include "RFM69registers_old.h" - -volatile uint8_t RFM69::DATA[RFM69_MAX_DATA_LEN]; -volatile uint8_t RFM69::_mode; // current transceiver state -volatile uint8_t RFM69::DATALEN; -volatile uint8_t RFM69::SENDERID; -volatile uint8_t RFM69::TARGETID; // should match _address -volatile uint8_t RFM69::PAYLOADLEN; -volatile uint8_t RFM69::ACK_REQUESTED; -volatile uint8_t -RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request -volatile int16_t -RFM69::RSSI; // most accurate RSSI during reception (closest to the reception) -RFM69* RFM69::selfPointer; - -bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID) -{ - //powerUp(); - //reset(); - const uint8_t CONFIG[][2] = { - /* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY }, - /* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, // no shaping - /* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, // default: 4.8 KBPS - /* 0x04 */ { REG_BITRATELSB, RF_BITRATELSB_55555}, - /* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_50000}, // default: 5KHz, (FDEV + BitRate / 2 <= 500KHz) - /* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_50000}, - - /* 0x07 */ { REG_FRFMSB, (uint8_t) (freqBand==RFM69_315MHZ ? RF_FRFMSB_315 : (freqBand==RFM69_433MHZ ? RF_FRFMSB_433 : (freqBand==RFM69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) }, - /* 0x08 */ { REG_FRFMID, (uint8_t) (freqBand==RFM69_315MHZ ? RF_FRFMID_315 : (freqBand==RFM69_433MHZ ? RF_FRFMID_433 : (freqBand==RFM69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) }, - /* 0x09 */ { REG_FRFLSB, (uint8_t) (freqBand==RFM69_315MHZ ? RF_FRFLSB_315 : (freqBand==RFM69_433MHZ ? RF_FRFLSB_433 : (freqBand==RFM69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) }, - - // looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm - // +17dBm and +20dBm are possible on RFM69HW - // +13dBm formula: Pout = -18 + OutputPower (with PA0 or PA1**) - // +17dBm formula: Pout = -14 + OutputPower (with PA1 and PA2)** - // +20dBm formula: Pout = -11 + OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) - ///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111}, - ///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, // over current protection (default is 95mA) - - // RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4KHz) - /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 }, // (BitRate < 2 * RxBw) - //for BR-19200: /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 }, - /* 0x25 */ { REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 }, // DIO0 is the only IRQ we're using - /* 0x26 */ { REG_DIOMAPPING2, RF_DIOMAPPING2_CLKOUT_OFF }, // DIO5 ClkOut disable for power saving - /* 0x28 */ { REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN }, // writing to this bit ensures that the FIFO & status flags are reset - /* 0x29 */ { REG_RSSITHRESH, 220 }, // must be set to dBm = (-Sensitivity / 2), default is 0xE4 = 228 so -114dBm - ///* 0x2D */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA - /* 0x2E */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 }, - /* 0x2F */ { REG_SYNCVALUE1, 0x2D }, // attempt to make this compatible with sync1 byte of RFM12B lib - /* 0x30 */ { REG_SYNCVALUE2, networkID }, // NETWORK ID - /* 0x37 */ { REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF }, - /* 0x38 */ { REG_PAYLOADLENGTH, 66 }, // in variable length mode: the max frame size, not used in TX - ///* 0x39 */ { REG_NODEADRS, nodeID }, // turned off because we're not using address filtering - /* 0x3C */ { REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE }, // TX on FIFO not empty - /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) - //for BR-19200: /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) - /* 0x6F */ { REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 }, // run DAGC continuously in RX mode for Fading Margin Improvement, recommended default for AfcLowBetaOn=0 - {255, 0} - }; - - hwDigitalWrite(_slaveSelectPin, HIGH); - hwPinMode(_slaveSelectPin, OUTPUT); - hwPinMode(_interruptPin, INPUT); - - RFM69_SPI.begin(); - unsigned long start = hwMillis(); - const uint8_t timeout = 50; - do { - writeReg(REG_SYNCVALUE1, 0xAA); - doYield(); - } while (readReg(REG_SYNCVALUE1) != 0xAA && hwMillis()-start < timeout); - if (hwMillis() - start >= timeout) { - // timeout: checking wiring or replace module - return false; - } - start = hwMillis(); - do { - writeReg(REG_SYNCVALUE1, 0x55); - doYield(); - } while (readReg(REG_SYNCVALUE1) != 0x55 && hwMillis()-start < timeout); - if (hwMillis() - start >= timeout) { - // timeout: checking wiring or replace module - return false; - } - for (uint8_t i = 0; CONFIG[i][0] != 255; i++) { - writeReg(CONFIG[i][0], CONFIG[i][1]); - } - - // Encryption is persistent between resets and can trip you up during debugging. - // Disable it during initialization so we always start from a known state. - encrypt(0); - - setHighPower(_isRFM69HW); // called regardless if it's a RFM69W or RFM69HW - setMode(RFM69_MODE_STANDBY); - start = hwMillis(); - while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && hwMillis()-start < timeout) { - doYield(); - } // wait for ModeReady - if (hwMillis()-start >= timeout) { - return false; - } - - //RFM69_SPI.usingInterrupt(_interruptNum); - attachInterrupt(_interruptNum, RFM69::isr0, RISING); - - selfPointer = this; - _address = nodeID; - return true; -} - -// return the frequency (in Hz) -uint32_t RFM69::getFrequency() -{ - return RFM69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg( - REG_FRFMID) << 8) + readReg(REG_FRFLSB)); -} - -// set the frequency (in Hz) -void RFM69::setFrequency(uint32_t freqHz) -{ - uint8_t oldMode = _mode; - if (oldMode == RFM69_MODE_TX) { - setMode(RFM69_MODE_RX); - } - freqHz /= RFM69_FSTEP; // divide down by FSTEP to get FRF - writeReg(REG_FRFMSB, freqHz >> 16); - writeReg(REG_FRFMID, freqHz >> 8); - writeReg(REG_FRFLSB, freqHz); - if (oldMode == RFM69_MODE_RX) { - setMode(RFM69_MODE_SYNTH); - } - setMode(oldMode); -} - -void RFM69::setMode(uint8_t newMode) -{ - if (newMode == _mode) { - return; - } - - const uint8_t currentOPMODE = readReg(REG_OPMODE) & 0xE3; - - switch (newMode) { - case RFM69_MODE_TX: - writeReg(REG_OPMODE, currentOPMODE | RF_OPMODE_TRANSMITTER); - if (_isRFM69HW) { - setHighPowerRegs(true); - } - break; - case RFM69_MODE_RX: - writeReg(REG_OPMODE, currentOPMODE | RF_OPMODE_RECEIVER); - if (_isRFM69HW) { - setHighPowerRegs(false); - } - break; - case RFM69_MODE_SYNTH: - writeReg(REG_OPMODE, currentOPMODE | RF_OPMODE_SYNTHESIZER); - break; - case RFM69_MODE_STANDBY: - writeReg(REG_OPMODE, currentOPMODE | RF_OPMODE_STANDBY); - break; - case RFM69_MODE_SLEEP: - writeReg(REG_OPMODE, currentOPMODE | RF_OPMODE_SLEEP); - break; - default: - return; - } - - // we are using packet mode, so this check is not really needed - // but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode - while (_mode == RFM69_MODE_SLEEP && - (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady - - _mode = newMode; -} - -//put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone() -void RFM69::sleep(void) -{ - setMode(RFM69_MODE_SLEEP); -} - -void RFM69::standBy(void) -{ - setMode(RFM69_MODE_STANDBY); -} -void RFM69::powerDown(void) -{ -#if defined(MY_RFM69_POWER_PIN) - hwDigitalWrite(MY_RFM69_POWER_PIN, LOW); -#endif -} -void RFM69::powerUp(void) -{ -#if defined(MY_RFM69_POWER_PIN) - hwDigitalWrite(MY_RFM69_POWER_PIN, HIGH); - delay(RFM69_POWERUP_DELAY_MS); -#endif -} -void RFM69::reset(void) -{ - // reset radio if RESET pin is defined -#ifdef MY_RFM69_RST_PIN - hwPinMode(MY_RFM69_RST_PIN, OUTPUT); - hwDigitalWrite(MY_RFM69_RST_PIN, HIGH); - // 100uS - delayMicroseconds(100); - hwDigitalWrite(MY_RFM69_RST_PIN, LOW); - // wait until chip ready - delay(5); -#endif -} - -bool RFM69::sanityCheck(void) -{ - bool result = true; - // check Bitrate - result &= readReg(REG_BITRATEMSB) == RF_BITRATEMSB_55555; - result &= readReg(REG_BITRATELSB) == RF_BITRATELSB_55555; - // default: 5KHz, (FDEV + BitRate / 2 <= 500KHz) - result &= readReg(REG_FDEVMSB) == RF_FDEVMSB_50000; - result &= readReg(REG_FDEVLSB) == RF_FDEVLSB_50000; - /* - // Check radio frequency band - result &= readReg(REG_FRFMSB) == (uint8_t)(MY_RFM69_FREQUENCY == RFM69_315MHZ ? RF_FRFMSB_315 : (MY_RFM69_FREQUENCY == RFM69_433MHZ ? RF_FRFMSB_433 : (MY_RFM69_FREQUENCY == RFM69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))); - result &= readReg(REG_FRFMID) == (uint8_t)(MY_RFM69_FREQUENCY == RFM69_315MHZ ? RF_FRFMID_315 : (MY_RFM69_FREQUENCY == RFM69_433MHZ ? RF_FRFMID_433 : (MY_RFM69_FREQUENCY == RFM69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))); - result &= readReg(REG_FRFLSB) == (uint8_t)(MY_RFM69_FREQUENCY == RFM69_315MHZ ? RF_FRFLSB_315 : (MY_RFM69_FREQUENCY == RFM69_433MHZ ? RF_FRFLSB_433 : (MY_RFM69_FREQUENCY == RFM69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))); - */ - return result; -} - -//set this node's address -void RFM69::setAddress(uint8_t addr) -{ - _address = addr; - writeReg(REG_NODEADRS, _address); -} - -//set this node's network id -void RFM69::setNetwork(uint8_t networkID) -{ - writeReg(REG_SYNCVALUE2, networkID); -} - -// set *transmit/TX* output power: 0=min, 31=max -// this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver -// the power configurations are explained in the SX1231H datasheet (Table 10 on p21; RegPaLevel p66): http://www.semtech.com/images/datasheet/sx1231h.pdf -// valid powerLevel parameter values are 0-31 and result in a directly proportional effect on the output/transmission power -// this function implements 2 modes as follows: -// - for RFM69W the range is from 0-31 [-18dBm to 13dBm] (PA0 only on RFIO pin) -// - for RFM69HW the range is from 0-31 [5dBm to 20dBm] (PA1 & PA2 on PA_BOOST pin & high Power PA settings - see section 3.3.7 in datasheet, p22) -void RFM69::setPowerLevel(uint8_t powerLevel) -{ - _powerLevel = (powerLevel > 31 ? 31 : powerLevel); - if (_isRFM69HW) { - _powerLevel /= 2; - } - writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | _powerLevel); -} - -bool RFM69::canSend() -{ - if (_mode == RFM69_MODE_RX && PAYLOADLEN == 0 && - readRSSI() < CSMA_LIMIT) { // if signal stronger than -100dBm is detected assume channel activity - setMode(RFM69_MODE_STANDBY); - return true; - } - return false; -} - -void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK) -{ - writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | - RF_PACKET2_RXRESTART); // avoid RX deadlocks - uint32_t now = hwMillis(); - while (!canSend() && hwMillis() - now < RFM69_CSMA_LIMIT_MS) { - receiveDone(); - } - sendFrame(toAddress, buffer, bufferSize, requestACK, false); -} - -// to increase the chance of getting a packet across, call this function instead of send -// and it handles all the ACK requesting/retrying for you :) -// The only twist is that you have to manually listen to ACK requests on the other side and send back the ACKs -// The reason for the semi-automaton is that the lib is interrupt driven and -// requires user action to read the received data and decide what to do with it -// replies usually take only 5..8ms at 50kbps@915MHz -bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, - uint8_t retries, uint8_t retryWaitTime) -{ - for (uint8_t i = 0; i <= retries; i++) { - send(toAddress, buffer, bufferSize, true); - uint32_t sentTime = hwMillis(); - while (hwMillis() - sentTime < retryWaitTime) { - if (ACKReceived(toAddress)) { - return true; - } - } - //Serial.print(" RETRY#"); Serial.println(i + 1); - } - return false; -} - -// should be polled immediately after sending a packet with ACK request -bool RFM69::ACKReceived(uint8_t fromNodeID) -{ - if (receiveDone()) { - return (SENDERID == fromNodeID || fromNodeID == RFM69_BROADCAST_ADDR) && ACK_RECEIVED; - } - return false; -} - -// check whether an ACK was requested in the last received packet (non-broadcasted packet) -bool RFM69::ACKRequested() -{ - return ACK_REQUESTED && (TARGETID != RFM69_BROADCAST_ADDR); -} - -// should be called immediately after reception in case sender wants ACK -void RFM69::sendACK(const void* buffer, uint8_t bufferSize) -{ - ACK_REQUESTED = - 0; // TWS added to make sure we don't end up in a timing race and infinite loop sending Acks - uint8_t sender = SENDERID; - int16_t _RSSI = RSSI; // save payload received RSSI value - writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | - RF_PACKET2_RXRESTART); // avoid RX deadlocks - uint32_t now = hwMillis(); - while (!canSend() && hwMillis() - now < RFM69_CSMA_LIMIT_MS) { - receiveDone(); - doYield(); - } - SENDERID = sender; // TWS: Restore SenderID after it gets wiped out by receiveDone() - sendFrame(sender, buffer, bufferSize, false, true); - RSSI = _RSSI; // restore payload RSSI -} - -void RFM69::interruptHook(uint8_t CTLbyte) -{ - (void)CTLbyte; -}; - -// internal function -void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK, - bool sendACK) -{ - setMode(RFM69_MODE_STANDBY); // turn off receiver to prevent reception while filling fifo - while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) {} // wait for ModeReady - writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00); // DIO0 is "Packet Sent" - if (bufferSize > RFM69_MAX_DATA_LEN) { - bufferSize = RFM69_MAX_DATA_LEN; - } - - // control byte - uint8_t CTLbyte = 0x00; - if (sendACK) { - CTLbyte = RFM69_CTL_SENDACK; - } else if (requestACK) { - CTLbyte = RFM69_CTL_REQACK; - } - - // write to FIFO - select(); - RFM69_SPI.transfer(REG_FIFO | 0x80); - RFM69_SPI.transfer(bufferSize + 3); - RFM69_SPI.transfer(toAddress); - RFM69_SPI.transfer(_address); - RFM69_SPI.transfer(CTLbyte); - - for (uint8_t i = 0; i < bufferSize; i++) { - RFM69_SPI.transfer(((uint8_t *)buffer)[i]); - } - unselect(); - - // no need to wait for transmit mode to be ready since its handled by the radio - setMode(RFM69_MODE_TX); - uint32_t txStart = hwMillis(); - while (hwDigitalRead(_interruptPin) == 0 && - hwMillis() - txStart < - RFM69_TX_LIMIT_MS) {} // wait for DIO0 to turn HIGH signalling transmission finish - //while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // wait for ModeReady - setMode(RFM69_MODE_STANDBY); -} - -// internal function - interrupt gets called when a packet is received -void IRQ_HANDLER_ATTR RFM69::interruptHandler() -{ - //hwPinMode(4, OUTPUT); - //hwDigitalWrite(4, 1); - if (_mode == RFM69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)) { - //RSSI = readRSSI(); - setMode(RFM69_MODE_STANDBY); - select(); - RFM69_SPI.transfer(REG_FIFO & 0x7F); - PAYLOADLEN = RFM69_SPI.transfer(0); - PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; // precaution - TARGETID = RFM69_SPI.transfer(0); - if(!(_promiscuousMode || TARGETID == _address || - TARGETID == - RFM69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in promiscuous mode - || PAYLOADLEN < - 3) { // address situation could receive packets that are malformed and don't fit this libraries extra fields - PAYLOADLEN = 0; - unselect(); - receiveBegin(); - //hwDigitalWrite(4, 0); - return; - } - - DATALEN = PAYLOADLEN - 3; - SENDERID = RFM69_SPI.transfer(0); - uint8_t CTLbyte = RFM69_SPI.transfer(0); - - ACK_RECEIVED = CTLbyte & RFM69_CTL_SENDACK; // extract ACK-received flag - ACK_REQUESTED = CTLbyte & RFM69_CTL_REQACK; // extract ACK-requested flag - - interruptHook(CTLbyte); // TWS: hook to derived class interrupt function - - for (uint8_t i = 0; i < DATALEN; i++) { - DATA[i] = RFM69_SPI.transfer(0); - } - if (DATALEN < RFM69_MAX_DATA_LEN) { - DATA[DATALEN] = 0; // add null at end of string - } - unselect(); - setMode(RFM69_MODE_RX); - } - RSSI = readRSSI(); - //hwDigitalWrite(4, 0); -} - -// internal function -void IRQ_HANDLER_ATTR RFM69::isr0() -{ - selfPointer->interruptHandler(); -} - -// internal function -void RFM69::receiveBegin() -{ - DATALEN = 0; - SENDERID = 0; - TARGETID = 0; - PAYLOADLEN = 0; - ACK_REQUESTED = 0; - ACK_RECEIVED = 0; - RSSI = 0; - if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) { - writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | - RF_PACKET2_RXRESTART); // avoid RX deadlocks - } - writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01); // set DIO0 to "PAYLOADREADY" in receive mode - setMode(RFM69_MODE_RX); -} - -// checks if a packet was received and/or puts transceiver in receive (ie RX or listen) mode -bool RFM69::receiveDone() -{ - //ATOMIC_BLOCK(ATOMIC_FORCEON) - //{ - noInterrupts(); // re-enabled in unselect() via setMode() or via receiveBegin() - if (_mode == RFM69_MODE_RX && PAYLOADLEN > 0) { - setMode(RFM69_MODE_STANDBY); // enables interrupts - return true; - } else if (_mode == RFM69_MODE_RX) { // already in RX no payload yet - interrupts(); // explicitly re-enable interrupts - return false; - } - receiveBegin(); - return false; - //} -} - -// To enable encryption: radio.encrypt("ABCDEFGHIJKLMNOP"); -// To disable encryption: radio.encrypt(null) or radio.encrypt(0) -// KEY HAS TO BE 16 bytes !!! -void RFM69::encrypt(const char* key) -{ - setMode(RFM69_MODE_STANDBY); - if (key != 0) { - select(); - RFM69_SPI.transfer(REG_AESKEY1 | 0x80); - for (uint8_t i = 0; i < 16; i++) { - RFM69_SPI.transfer(key[i]); - } - unselect(); - } - writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFE) | (key ? 1 : 0)); -} - -// get the received signal strength indicator (RSSI) -int16_t RFM69::readRSSI(bool forceTrigger) -{ - int16_t rssi = 0; - if (forceTrigger) { - // RSSI trigger not needed if DAGC is in continuous mode - writeReg(REG_RSSICONFIG, RF_RSSI_START); - while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00) {} // wait for RSSI_Ready - } - rssi = -readReg(REG_RSSIVALUE); - rssi >>= 1; - return rssi; -} - -uint8_t RFM69::readReg(uint8_t addr) -{ - select(); - RFM69_SPI.transfer(addr & 0x7F); - uint8_t regval = RFM69_SPI.transfer(0); - unselect(); - return regval; -} - -void RFM69::writeReg(uint8_t addr, uint8_t value) -{ - select(); - RFM69_SPI.transfer(addr | 0x80); - RFM69_SPI.transfer(value); - unselect(); -} - -// select the RFM69 transceiver (save SPI settings, set CS low) -void RFM69::select() -{ - noInterrupts(); -#if defined (SPCR) && defined (SPSR) - // save current SPI settings - _SPCR = SPCR; - _SPSR = SPSR; -#endif - // set RFM69 SPI settings - RFM69_SPI.setDataMode(SPI_MODE0); - RFM69_SPI.setBitOrder(MSBFIRST); - RFM69_SPI.setClockDivider(RFM69_CLOCK_DIV); - hwDigitalWrite(_slaveSelectPin, LOW); -} - -// unselect the RFM69 transceiver (set CS high, restore SPI settings) -void RFM69::unselect() -{ - hwDigitalWrite(_slaveSelectPin, HIGH); - // restore SPI settings to what they were before talking to RFM69 -#if defined (SPCR) && defined (SPSR) - SPCR = _SPCR; - SPSR = _SPSR; -#endif - interrupts(); -} - -// true = disable filtering to capture all frames on network -// false = enable node/broadcast filtering to capture only frames sent to this/broadcast address -void RFM69::promiscuous(bool onOff) -{ - _promiscuousMode = onOff; - //writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST)); -} - -// for RFM69HW only: you must call setHighPower(true) after initialize() or else transmission won't work -void RFM69::setHighPower(bool onOff) -{ - _isRFM69HW = onOff; - writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON); - if (_isRFM69HW) { // turning ON - writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | - RF_PALEVEL_PA2_ON); // enable P1 & P2 amplifier stages - } else { - writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | - _powerLevel); // enable P0 only - } -} - -// internal function -void RFM69::setHighPowerRegs(bool onOff) -{ - writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55); - writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70); -} - -// set the slave select (CS) pin -void RFM69::setCS(uint8_t newSPISlaveSelect) -{ - _slaveSelectPin = newSPISlaveSelect; - hwDigitalWrite(_slaveSelectPin, HIGH); - hwPinMode(_slaveSelectPin, OUTPUT); -} - -//for debugging -#define REGISTER_DETAIL 0 -#if REGISTER_DETAIL -// SERIAL PRINT -// replace Serial.print("string") with SerialPrint("string") -#define SerialPrint(x) SerialPrint_P(PSTR(x)) -void SerialWrite ( uint8_t c ) -{ - Serial.write ( c ); -} - -void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite ) -{ - for (uint8_t c; (c = pgm_read_byte(str)); str++) { - (*f)(c); - } -} -#endif - -void RFM69::readAllRegs() -{ -#if REGISTER_DETAIL - int capVal; - - //... State Variables for intelligent decoding - uint8_t modeFSK = 0; - int bitRate = 0; - int freqDev = 0; - long freqCenter = 0; -#endif - - Serial.println("Address - HEX - BIN"); - for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++) { - select(); - RFM69_SPI.transfer(regAddr & 0x7F); // send address + r/w bit - uint8_t regVal = RFM69_SPI.transfer(0); - unselect(); - - Serial.print(regAddr, HEX); - Serial.print(" - "); - Serial.print(regVal,HEX); - Serial.print(" - "); - Serial.println(regVal,BIN); - -#if REGISTER_DETAIL - switch ( regAddr ) { - case 0x1 : { - SerialPrint ( "Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : " ); - if ( 0x80 & regVal ) { - SerialPrint ( "1 -> Mode is forced by the user\n" ); - } else { - SerialPrint ( "0 -> Operating mode as selected with Mode bits in RegOpMode is automatically reached with the Sequencer\n" ); - } - - SerialPrint( "\nEnables Listen mode, should be enabled whilst in Standby mode:\nListenOn : " ); - if ( 0x40 & regVal ) { - SerialPrint ( "1 -> On\n" ); - } else { - SerialPrint ( "0 -> Off ( see section 4.3)\n" ); - } - - SerialPrint( "\nAborts Listen mode when set together with ListenOn=0 See section 4.3.4 for details (Always reads 0.)\n" ); - if ( 0x20 & regVal ) { - SerialPrint ( "ERROR - ListenAbort should NEVER return 1 this is a write only register\n" ); - } - - SerialPrint("\nTransceiver's operating modes:\nMode : "); - capVal = (regVal >> 2) & 0x7; - if ( capVal == 0b000 ) { - SerialPrint ( "000 -> Sleep mode (SLEEP)\n" ); - } else if ( capVal = 0b001 ) { - SerialPrint ( "001 -> Standby mode (STDBY)\n" ); - } else if ( capVal = 0b010 ) { - SerialPrint ( "010 -> Frequency Synthesizer mode (FS)\n" ); - } else if ( capVal = 0b011 ) { - SerialPrint ( "011 -> Transmitter mode (TX)\n" ); - } else if ( capVal = 0b100 ) { - SerialPrint ( "100 -> Receiver Mode (RX)\n" ); - } else { - Serial.print( capVal, BIN ); - SerialPrint ( " -> RESERVED\n" ); - } - SerialPrint ( "\n" ); - break; - } - - case 0x2 : { - - SerialPrint("Data Processing mode:\nDataMode : "); - capVal = (regVal >> 5) & 0x3; - if ( capVal == 0b00 ) { - SerialPrint ( "00 -> Packet mode\n" ); - } else if ( capVal == 0b01 ) { - SerialPrint ( "01 -> reserved\n" ); - } else if ( capVal == 0b10 ) { - SerialPrint ( "10 -> Continuous mode with bit synchronizer\n" ); - } else if ( capVal == 0b11 ) { - SerialPrint ( "11 -> Continuous mode without bit synchronizer\n" ); - } - - SerialPrint("\nModulation scheme:\nModulation Type : "); - capVal = (regVal >> 3) & 0x3; - if ( capVal == 0b00 ) { - SerialPrint ( "00 -> FSK\n" ); - modeFSK = 1; - } else if ( capVal == 0b01 ) { - SerialPrint ( "01 -> OOK\n" ); - } else if ( capVal == 0b10 ) { - SerialPrint ( "10 -> reserved\n" ); - } else if ( capVal == 0b11 ) { - SerialPrint ( "11 -> reserved\n" ); - } - - SerialPrint("\nData shaping: "); - if ( modeFSK ) { - SerialPrint( "in FSK:\n" ); - } else { - SerialPrint( "in OOK:\n" ); - } - SerialPrint ("ModulationShaping : "); - capVal = regVal & 0x3; - if ( modeFSK ) { - if ( capVal == 0b00 ) { - SerialPrint ( "00 -> no shaping\n" ); - } else if ( capVal == 0b01 ) { - SerialPrint ( "01 -> Gaussian filter, BT = 1.0\n" ); - } else if ( capVal == 0b10 ) { - SerialPrint ( "10 -> Gaussian filter, BT = 0.5\n" ); - } else if ( capVal == 0b11 ) { - SerialPrint ( "11 -> Gaussian filter, BT = 0.3\n" ); - } - } else { - if ( capVal == 0b00 ) { - SerialPrint ( "00 -> no shaping\n" ); - } else if ( capVal == 0b01 ) { - SerialPrint ( "01 -> filtering with f(cutoff) = BR\n" ); - } else if ( capVal == 0b10 ) { - SerialPrint ( "10 -> filtering with f(cutoff) = 2*BR\n" ); - } else if ( capVal == 0b11 ) { - SerialPrint ( "ERROR - 11 is reserved\n" ); - } - } - - SerialPrint ( "\n" ); - break; - } - - case 0x3 : { - bitRate = (regVal << 8); - break; - } - - case 0x4 : { - bitRate |= regVal; - SerialPrint ( "Bit Rate (Chip Rate when Manchester encoding is enabled)\nBitRate : "); - unsigned long val = 32UL * 1000UL * 1000UL / bitRate; - Serial.println( val ); - SerialPrint( "\n" ); - break; - } - - case 0x5 : { - freqDev = ( (regVal & 0x3f) << 8 ); - break; - } - - case 0x6 : { - freqDev |= regVal; - SerialPrint( "Frequency deviation\nFdev : " ); - unsigned long val = 61UL * freqDev; - Serial.println( val ); - SerialPrint ( "\n" ); - break; - } - - case 0x7 : { - unsigned long tempVal = regVal; - freqCenter = ( tempVal << 16 ); - break; - } - - case 0x8 : { - unsigned long tempVal = regVal; - freqCenter = freqCenter | ( tempVal << 8 ); - break; - } - - case 0x9 : { - freqCenter = freqCenter | regVal; - SerialPrint ( "RF Carrier frequency\nFRF : " ); - unsigned long val = 61UL * freqCenter; - Serial.println( val ); - SerialPrint( "\n" ); - break; - } - - case 0xa : { - SerialPrint ( "RC calibration control & status\nRcCalDone : " ); - if ( 0x40 & regVal ) { - SerialPrint ( "1 -> RC calibration is over\n" ); - } else { - SerialPrint ( "0 -> RC calibration is in progress\n" ); - } - - SerialPrint ( "\n" ); - break; - } - - case 0xb : { - SerialPrint ( "Improved AFC routine for signals with modulation index lower than 2. Refer to section 3.4.16 for details\nAfcLowBetaOn : " ); - if ( 0x20 & regVal ) { - SerialPrint ( "1 -> Improved AFC routine\n" ); - } else { - SerialPrint ( "0 -> Standard AFC routine\n" ); - } - SerialPrint ( "\n" ); - break; - } - - case 0xc : { - SerialPrint ( "Reserved\n\n" ); - break; - } - - case 0xd : { - byte val; - SerialPrint ( "Resolution of Listen mode Idle time (calibrated RC osc):\nListenResolIdle : " ); - val = regVal >> 6; - if ( val == 0b00 ) { - SerialPrint ( "00 -> reserved\n" ); - } else if ( val == 0b01 ) { - SerialPrint ( "01 -> 64 us\n" ); - } else if ( val == 0b10 ) { - SerialPrint ( "10 -> 4.1 ms\n" ); - } else if ( val == 0b11 ) { - SerialPrint ( "11 -> 262 ms\n" ); - } - - SerialPrint ( "\nResolution of Listen mode Rx time (calibrated RC osc):\nListenResolRx : " ); - val = (regVal >> 4) & 0x3; - if ( val == 0b00 ) { - SerialPrint ( "00 -> reserved\n" ); - } else if ( val == 0b01 ) { - SerialPrint ( "01 -> 64 us\n" ); - } else if ( val == 0b10 ) { - SerialPrint ( "10 -> 4.1 ms\n" ); - } else if ( val == 0b11 ) { - SerialPrint ( "11 -> 262 ms\n" ); - } - - SerialPrint ( "\nCriteria for packet acceptance in Listen mode:\nListenCriteria : " ); - if ( 0x8 & regVal ) { - SerialPrint ( "1 -> signal strength is above RssiThreshold and SyncAddress matched\n" ); - } else { - SerialPrint ( "0 -> signal strength is above RssiThreshold\n" ); - } - - SerialPrint ( "\nAction taken after acceptance of a packet in Listen mode:\nListenEnd : " ); - val = (regVal >> 1 ) & 0x3; - if ( val == 0b00 ) { - SerialPrint ( "00 -> chip stays in Rx mode. Listen mode stops and must be disabled (see section 4.3)\n" ); - } else if ( val == 0b01 ) { - SerialPrint ( "01 -> chip stays in Rx mode until PayloadReady or Timeout interrupt occurs. It then goes to the mode defined by Mode. Listen mode stops and must be disabled (see section 4.3)\n" ); - } else if ( val == 0b10 ) { - SerialPrint ( "10 -> chip stays in Rx mode until PayloadReady or Timeout occurs. Listen mode then resumes in Idle state. FIFO content is lost at next Rx wakeup.\n" ); - } else if ( val == 0b11 ) { - SerialPrint ( "11 -> Reserved\n" ); - } - - - SerialPrint ( "\n" ); - break; - } - - default : { - } - } -#endif - } - unselect(); -} - -uint8_t RFM69::readTemperature(uint8_t calFactor) // returns centigrade -{ - setMode(RFM69_MODE_STANDBY); - writeReg(REG_TEMP1, RF_TEMP1_MEAS_START); - while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) {} - return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF + - calFactor; // 'complement' corrects the slope, rising temp = rising val -} // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction - -void RFM69::rcCalibration() -{ - writeReg(REG_OSC1, RF_OSC1_RCCAL_START); - while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00) {} -} diff --git a/lib/MySensors/hal/transport/RFM69/driver/old/RFM69_old.h b/lib/MySensors/hal/transport/RFM69/driver/old/RFM69_old.h deleted file mode 100644 index 4b3f9524..00000000 --- a/lib/MySensors/hal/transport/RFM69/driver/old/RFM69_old.h +++ /dev/null @@ -1,232 +0,0 @@ -// ********************************************************************************** -// Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech SX1231/1231H -// ********************************************************************************** -// Copyright Felix Rusu (2014), felix@lowpowerlab.com -// http://lowpowerlab.com/ -// ********************************************************************************** -// License -// ********************************************************************************** -// 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 . -// -// Licence can be viewed at -// http://www.gnu.org/licenses/gpl-3.0.txt -// -// Please maintain this license information along with authorship -// and copyright notices in any redistribution of this code -// ********************************************************************************** -#ifndef RFM69_h -#define RFM69_h - -#if !defined(RFM69_SPI) -#define RFM69_SPI hwSPI //!< default SPI -#endif - -#define RFM69_MAX_DATA_LEN (61u) // to take advantage of the built in AES/CRC we want to limit the frame size to the internal FIFO size (66 bytes - 3 bytes overhead - 2 bytes crc) - -#if defined(ARDUINO_ARCH_AVR) -#if defined(__AVR_ATmega32U4__) -#define DEFAULT_RFM69_IRQ_PIN (3) //!< DEFAULT_RFM69_IRQ_PIN -#else -#define DEFAULT_RFM69_IRQ_PIN (2) //!< DEFAULT_RFM69_IRQ_PIN -#endif -#define DEFAULT_RFM69_IRQ_NUM digitalPinToInterrupt(MY_RFM69_IRQ_PIN) //!< DEFAULT_RFM69_IRQ_NUM -#elif defined(ARDUINO_ARCH_ESP8266) -#define DEFAULT_RFM69_IRQ_PIN (5) //!< DEFAULT_RFM69_IRQ_PIN -#define DEFAULT_RFM69_IRQ_NUM digitalPinToInterrupt(MY_RFM69_IRQ_PIN) //!< DEFAULT_RFM69_IRQ_NUM -#elif defined(ARDUINO_ARCH_ESP32) -#define DEFAULT_RFM69_IRQ_PIN (16) //!< DEFAULT_RFM69_IRQ_PIN -#define DEFAULT_RFM69_IRQ_NUM digitalPinToInterrupt(DEFAULT_RFM69_IRQ_PIN) //!< DEFAULT_RFM69_IRQ_NUM -#elif defined(ARDUINO_ARCH_SAMD) -#define DEFAULT_RFM69_IRQ_PIN (2) //!< DEFAULT_RFM69_IRQ_PIN -#define DEFAULT_RFM69_IRQ_NUM digitalPinToInterrupt(MY_RFM69_IRQ_PIN) //!< DEFAULT_RFM69_IRQ_NUM -#elif defined(LINUX_ARCH_RASPBERRYPI) -#define DEFAULT_RFM69_IRQ_PIN (22) //!< DEFAULT_RFM69_IRQ_PIN -#define DEFAULT_RFM69_IRQ_NUM DEFAULT_RFM69_IRQ_PIN //!< DEFAULT_RFM69_IRQ_NUM -#elif defined(ARDUINO_ARCH_STM32F1) -#define DEFAULT_RFM69_IRQ_PIN (PA3) //!< DEFAULT_RFM69_IRQ_PIN -#define DEFAULT_RFM69_IRQ_NUM DEFAULT_RFM69_IRQ_PIN //!< DEFAULT_RFM69_IRQ_NUM -#elif defined(TEENSYDUINO) -#define DEFAULT_RFM69_IRQ_PIN (8) //!< DEFAULT_RFM69_IRQ_PIN -#define DEFAULT_RFM69_IRQ_NUM digitalPinToInterrupt(MY_RFM69_IRQ_PIN) //!< DEFAULT_RFM69_IRQ_NUM -#else -#define DEFAULT_RFM69_IRQ_PIN (2) //!< DEFAULT_RFM69_IRQ_PIN -#define DEFAULT_RFM69_IRQ_NUM (2) //!< DEFAULT_RFM69_IRQ_NUM -#endif - -#define DEFAULT_RFM69_CS_PIN (SS) //!< DEFAULT_RFM69_CS_PIN - -// SPI clock divier for non-transaction implementations -#if (MY_RFM69_SPI_SPEED >= F_CPU / 2) -#define RFM69_CLOCK_DIV SPI_CLOCK_DIV2 //!< SPI clock divider 2 -#elif (MY_RFM69_SPI_SPEED >= F_CPU / 4) -#define RFM69_CLOCK_DIV SPI_CLOCK_DIV4 //!< SPI clock divider 4 -#elif (MY_RFM69_SPI_SPEED >= F_CPU / 8) -#define RFM69_CLOCK_DIV SPI_CLOCK_DIV8 //!< SPI clock divider 8 -#elif (MY_RFM69_SPI_SPEED >= F_CPU / 16) -#define RFM69_CLOCK_DIV SPI_CLOCK_DIV16 //!< SPI clock divider 16 -#elif (MY_RFM69_SPI_SPEED >= F_CPU / 32) -#define RFM69_CLOCK_DIV SPI_CLOCK_DIV32 //!< SPI clock divider 32 -#elif (MY_RFM69_SPI_SPEED >= F_CPU / 64) -#define RFM69_CLOCK_DIV SPI_CLOCK_DIV64 //!< SPI clock divider 64 -#elif (MY_RFM69_SPI_SPEED >= F_CPU / 128) -#define RFM69_CLOCK_DIV SPI_CLOCK_DIV128 //!< SPI clock divider 128 -#else -#define RFM69_CLOCK_DIV SPI_CLOCK_DIV256 //!< SPI clock divider 256 -#endif - -// powerup delay -#define RFM69_POWERUP_DELAY_MS (100u) //!< Power up delay, allow VCC to settle, transport to become fully operational - -#define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access -#define RFM69_MODE_SLEEP 0 // XTAL OFF -#define RFM69_MODE_STANDBY 1 // XTAL ON -#define RFM69_MODE_SYNTH 2 // PLL ON -#define RFM69_MODE_RX 3 // RX MODE -#define RFM69_MODE_TX 4 // TX MODE - -// available frequency bands -#define RFM69_315MHZ 31 // non trivial values to avoid misconfiguration -#define RFM69_433MHZ 43 -#define RFM69_868MHZ 86 -#define RFM69_915MHZ 91 - -#define null 0 -#define COURSE_TEMP_COEF -90 // puts the temperature reading in the ballpark, user can fine tune the returned value -#define RFM69_BROADCAST_ADDR 255 -#define RFM69_CSMA_LIMIT_MS 1000 -#define RFM69_TX_LIMIT_MS 1000 - -#define RFM69_FXOSC (32*1000000ul) //!< The crystal oscillator frequency of the module, 32MHz -#define RFM69_FSTEP (RFM69_FXOSC / 524288ul) //!< The Frequency Synthesizer step - -// TWS: define CTLbyte bits -#define RFM69_CTL_SENDACK 0x80 -#define RFM69_CTL_REQACK 0x40 - -/** RFM69 class */ -class RFM69 -{ -public: - static volatile uint8_t DATA[RFM69_MAX_DATA_LEN]; //!< recv/xmit buf, including hdr & crc bytes - static volatile uint8_t DATALEN; //!< DATALEN - static volatile uint8_t SENDERID; //!< SENDERID - static volatile uint8_t TARGETID; //!< should match _address - static volatile uint8_t PAYLOADLEN; //!< PAYLOADLEN - static volatile uint8_t ACK_REQUESTED; //!< ACK_REQUESTED - static volatile uint8_t - ACK_RECEIVED; //!< Should be polled immediately after sending a packet with ACK requestwith ACK request - static volatile int16_t RSSI; //!< most accurate RSSI during reception (closest to the reception) - static volatile uint8_t _mode; //!< should be protected? - - /** - * @brief Constructor - * - * @param slaveSelectPin ChipSelect pin. - * @param interruptPin Interrupt pin. - * @param isRFM69HW Set to @c true to indicate RFM69HW variant. - * @param interruptNum Interrupt number. - */ - // cppcheck-suppress uninitMemberVar - RFM69(uint8_t slaveSelectPin=MY_RFM69_CS_PIN, uint8_t interruptPin=MY_RFM69_IRQ_PIN, - bool isRFM69HW=false, - uint8_t interruptNum=digitalPinToInterrupt(MY_RFM69_IRQ_PIN)) - { - _slaveSelectPin = slaveSelectPin; - _interruptPin = interruptPin; - _interruptNum = interruptNum; - _mode = RFM69_MODE_STANDBY; - _promiscuousMode = false; - _powerLevel = 31; - _isRFM69HW = isRFM69HW; - _address = RFM69_BROADCAST_ADDR; -#if !defined(SPI_HAS_TRANSACTION) -#if defined (SPCR) && defined (SPSR) - _SPCR = 0; - _SPSR = 0; -#endif -#if defined (SREG) - _SREG = 0; -#endif -#endif // SPI_HAS_TRANSACTION - } - - bool initialize(uint8_t freqBand, uint8_t ID, uint8_t networkID=1); //!< initialize - void setAddress(uint8_t addr); //!< setAddress - void setNetwork(uint8_t networkID); //!< setNetwork - bool canSend(); //!< canSend - virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, - bool requestACK=false); //!< send - virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, - uint8_t retries=5, uint8_t retryWaitTime= - 200); //!< sendWithRetry (40ms roundtrip req for 61byte packets, adjusted) - virtual bool receiveDone(); //!< receiveDone - bool ACKReceived(uint8_t fromNodeID); //!< ACKReceived - bool ACKRequested(); //!< ACKRequested - virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0); //!< sendACK - uint32_t getFrequency(); //!< getFrequency - void setFrequency(uint32_t freqHz); //!< setFrequency - void encrypt(const char* key); //!< encrypt - void setCS(uint8_t newSPISlaveSelect); //!< setCS - int16_t readRSSI(bool forceTrigger=false); //!< readRSSI - void promiscuous(bool onOff=true); //!< promiscuous - virtual void setHighPower(bool onOFF= - true); //!< setHighPower (have to call it after initialize for RFM69HW) - virtual void setPowerLevel(uint8_t level); //!< setPowerLevel (reduce/increase transmit power level) - void sleep(void); //!< sleep - void standBy(void); //!< standBy - void powerDown(void); //!< powerDown - void powerUp(void); //!< powerUp - void reset(void); //!< reset - bool sanityCheck(void); //!< sanityCheck - uint8_t readTemperature(uint8_t calFactor=0); //!< readTemperature (get CMOS temperature (8bit)) - void rcCalibration(); //!< rcCalibration (calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy]) - - // allow hacking registers by making these public - uint8_t readReg(uint8_t addr); //!< readReg - void writeReg(uint8_t addr, uint8_t val); //!< writeReg - void readAllRegs(); //!< readAllRegs -protected: - static void isr0(); //!< isr0 - void virtual interruptHandler(); //!< interruptHandler - virtual void interruptHook(uint8_t CTLbyte); //!< interruptHook - virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, - bool sendACK=false); //!< sendFrame - - static RFM69* selfPointer; //!< selfPointer - uint8_t _slaveSelectPin; //!< _slaveSelectPin - uint8_t _interruptPin; //!< _interruptPin - uint8_t _interruptNum; //!< _interruptNum - uint8_t _address; //!< _address - bool _promiscuousMode; //!< _promiscuousMode - uint8_t _powerLevel; //!< _powerLevel - bool _isRFM69HW; //!< _isRFM69HW -#if defined (SPCR) && defined (SPSR) - uint8_t _SPCR; //!< _SPCR - uint8_t _SPSR; //!< _SPSR -#endif -#if defined (SREG) - uint8_t _SREG; //!< _SREG -#endif - - virtual void receiveBegin(); //!< receiveBegin - virtual void setMode(uint8_t mode); //!< setMode - virtual void setHighPowerRegs(bool onOff); //!< setHighPowerRegs - virtual void select(); //!< select - virtual void unselect(); //!< unselect -}; - -#endif diff --git a/lib/MySensors/hal/transport/RFM69/driver/old/RFM69registers_old.h b/lib/MySensors/hal/transport/RFM69/driver/old/RFM69registers_old.h deleted file mode 100644 index cb383592..00000000 --- a/lib/MySensors/hal/transport/RFM69/driver/old/RFM69registers_old.h +++ /dev/null @@ -1,1109 +0,0 @@ -// ********************************************************************************** -// Registers used in driver definition for HopeRF RFM69W/RFM69HW, Semtech SX1231/1231H -// ********************************************************************************** -// Copyright Felix Rusu (2015), felix@lowpowerlab.com -// http://lowpowerlab.com/ -// ********************************************************************************** -// License -// ********************************************************************************** -// 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 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will -// be useful, but WITHOUT ANY WARRANTY; without even the -// implied warranty of MERCHANTABILITY or FITNESS FOR A -// PARTICULAR PURPOSE. See the GNU General Public -// License for more details. -// -// You should have received a copy of the GNU General -// Public License along with this program; if not, write -// to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Licence can be viewed at -// http://www.fsf.org/licenses/gpl.txt -// -// Please maintain this license information along with authorship -// and copyright notices in any redistribution of this code -// ********************************************************************************** -// RFM69/SX1231 Internal registers addresses -//************************************************** -#define REG_FIFO 0x00 -#define REG_OPMODE 0x01 -#define REG_DATAMODUL 0x02 -#define REG_BITRATEMSB 0x03 -#define REG_BITRATELSB 0x04 -#define REG_FDEVMSB 0x05 -#define REG_FDEVLSB 0x06 -#define REG_FRFMSB 0x07 -#define REG_FRFMID 0x08 -#define REG_FRFLSB 0x09 -#define REG_OSC1 0x0A -#define REG_AFCCTRL 0x0B -#define REG_LOWBAT 0x0C -#define REG_LISTEN1 0x0D -#define REG_LISTEN2 0x0E -#define REG_LISTEN3 0x0F -#define REG_VERSION 0x10 -#define REG_PALEVEL 0x11 -#define REG_PARAMP 0x12 -#define REG_OCP 0x13 -#define REG_AGCREF 0x14 // not present on RFM69/SX1231 -#define REG_AGCTHRESH1 0x15 // not present on RFM69/SX1231 -#define REG_AGCTHRESH2 0x16 // not present on RFM69/SX1231 -#define REG_AGCTHRESH3 0x17 // not present on RFM69/SX1231 -#define REG_LNA 0x18 -#define REG_RXBW 0x19 -#define REG_AFCBW 0x1A -#define REG_OOKPEAK 0x1B -#define REG_OOKAVG 0x1C -#define REG_OOKFIX 0x1D -#define REG_AFCFEI 0x1E -#define REG_AFCMSB 0x1F -#define REG_AFCLSB 0x20 -#define REG_FEIMSB 0x21 -#define REG_FEILSB 0x22 -#define REG_RSSICONFIG 0x23 -#define REG_RSSIVALUE 0x24 -#define REG_DIOMAPPING1 0x25 -#define REG_DIOMAPPING2 0x26 -#define REG_IRQFLAGS1 0x27 -#define REG_IRQFLAGS2 0x28 -#define REG_RSSITHRESH 0x29 -#define REG_RXTIMEOUT1 0x2A -#define REG_RXTIMEOUT2 0x2B -#define REG_PREAMBLEMSB 0x2C -#define REG_PREAMBLELSB 0x2D -#define REG_SYNCCONFIG 0x2E -#define REG_SYNCVALUE1 0x2F -#define REG_SYNCVALUE2 0x30 -#define REG_SYNCVALUE3 0x31 -#define REG_SYNCVALUE4 0x32 -#define REG_SYNCVALUE5 0x33 -#define REG_SYNCVALUE6 0x34 -#define REG_SYNCVALUE7 0x35 -#define REG_SYNCVALUE8 0x36 -#define REG_PACKETCONFIG1 0x37 -#define REG_PAYLOADLENGTH 0x38 -#define REG_NODEADRS 0x39 -#define REG_BROADCASTADRS 0x3A -#define REG_AUTOMODES 0x3B -#define REG_FIFOTHRESH 0x3C -#define REG_PACKETCONFIG2 0x3D -#define REG_AESKEY1 0x3E -#define REG_AESKEY2 0x3F -#define REG_AESKEY3 0x40 -#define REG_AESKEY4 0x41 -#define REG_AESKEY5 0x42 -#define REG_AESKEY6 0x43 -#define REG_AESKEY7 0x44 -#define REG_AESKEY8 0x45 -#define REG_AESKEY9 0x46 -#define REG_AESKEY10 0x47 -#define REG_AESKEY11 0x48 -#define REG_AESKEY12 0x49 -#define REG_AESKEY13 0x4A -#define REG_AESKEY14 0x4B -#define REG_AESKEY15 0x4C -#define REG_AESKEY16 0x4D -#define REG_TEMP1 0x4E -#define REG_TEMP2 0x4F -#define REG_TESTLNA 0x58 -#define REG_TESTPA1 0x5A // only present on RFM69HW/SX1231H -#define REG_TESTPA2 0x5C // only present on RFM69HW/SX1231H -#define REG_TESTDAGC 0x6F - -//****************************************************** -// RF69/SX1231 bit control definition -//****************************************************** - -// RegOpMode -#define RF_OPMODE_SEQUENCER_OFF 0x80 -#define RF_OPMODE_SEQUENCER_ON 0x00 // Default - -#define RF_OPMODE_LISTEN_ON 0x40 -#define RF_OPMODE_LISTEN_OFF 0x00 // Default - -#define RF_OPMODE_LISTENABORT 0x20 - -#define RF_OPMODE_SLEEP 0x00 -#define RF_OPMODE_STANDBY 0x04 // Default -#define RF_OPMODE_SYNTHESIZER 0x08 -#define RF_OPMODE_TRANSMITTER 0x0C -#define RF_OPMODE_RECEIVER 0x10 - - -// RegDataModul -#define RF_DATAMODUL_DATAMODE_PACKET 0x00 // Default -#define RF_DATAMODUL_DATAMODE_CONTINUOUS 0x40 -#define RF_DATAMODUL_DATAMODE_CONTINUOUSNOBSYNC 0x60 - -#define RF_DATAMODUL_MODULATIONTYPE_FSK 0x00 // Default -#define RF_DATAMODUL_MODULATIONTYPE_OOK 0x08 - -#define RF_DATAMODUL_MODULATIONSHAPING_00 0x00 // Default -#define RF_DATAMODUL_MODULATIONSHAPING_01 0x01 -#define RF_DATAMODUL_MODULATIONSHAPING_10 0x02 -#define RF_DATAMODUL_MODULATIONSHAPING_11 0x03 - - -// RegBitRate (bits/sec) example bit rates -#define RF_BITRATEMSB_1200 0x68 -#define RF_BITRATELSB_1200 0x2B -#define RF_BITRATEMSB_2400 0x34 -#define RF_BITRATELSB_2400 0x15 -#define RF_BITRATEMSB_4800 0x1A // Default -#define RF_BITRATELSB_4800 0x0B // Default -#define RF_BITRATEMSB_9600 0x0D -#define RF_BITRATELSB_9600 0x05 -#define RF_BITRATEMSB_19200 0x06 -#define RF_BITRATELSB_19200 0x83 -#define RF_BITRATEMSB_38400 0x03 -#define RF_BITRATELSB_38400 0x41 - -#define RF_BITRATEMSB_38323 0x03 -#define RF_BITRATELSB_38323 0x43 - -#define RF_BITRATEMSB_34482 0x03 -#define RF_BITRATELSB_34482 0xA0 - -#define RF_BITRATEMSB_76800 0x01 -#define RF_BITRATELSB_76800 0xA1 -#define RF_BITRATEMSB_153600 0x00 -#define RF_BITRATELSB_153600 0xD0 -#define RF_BITRATEMSB_57600 0x02 -#define RF_BITRATELSB_57600 0x2C -#define RF_BITRATEMSB_115200 0x01 -#define RF_BITRATELSB_115200 0x16 -#define RF_BITRATEMSB_12500 0x0A -#define RF_BITRATELSB_12500 0x00 -#define RF_BITRATEMSB_25000 0x05 -#define RF_BITRATELSB_25000 0x00 -#define RF_BITRATEMSB_50000 0x02 -#define RF_BITRATELSB_50000 0x80 -#define RF_BITRATEMSB_100000 0x01 -#define RF_BITRATELSB_100000 0x40 -#define RF_BITRATEMSB_150000 0x00 -#define RF_BITRATELSB_150000 0xD5 -#define RF_BITRATEMSB_200000 0x00 -#define RF_BITRATELSB_200000 0xA0 -#define RF_BITRATEMSB_250000 0x00 -#define RF_BITRATELSB_250000 0x80 -#define RF_BITRATEMSB_300000 0x00 -#define RF_BITRATELSB_300000 0x6B -#define RF_BITRATEMSB_32768 0x03 -#define RF_BITRATELSB_32768 0xD1 -// custom bit rates -#define RF_BITRATEMSB_55555 0x02 -#define RF_BITRATELSB_55555 0x40 -#define RF_BITRATEMSB_200KBPS 0x00 -#define RF_BITRATELSB_200KBPS 0xa0 - - -// RegFdev - frequency deviation (Hz) -#define RF_FDEVMSB_2000 0x00 -#define RF_FDEVLSB_2000 0x21 -#define RF_FDEVMSB_5000 0x00 // Default -#define RF_FDEVLSB_5000 0x52 // Default -#define RF_FDEVMSB_7500 0x00 -#define RF_FDEVLSB_7500 0x7B -#define RF_FDEVMSB_10000 0x00 -#define RF_FDEVLSB_10000 0xA4 -#define RF_FDEVMSB_15000 0x00 -#define RF_FDEVLSB_15000 0xF6 -#define RF_FDEVMSB_20000 0x01 -#define RF_FDEVLSB_20000 0x48 -#define RF_FDEVMSB_25000 0x01 -#define RF_FDEVLSB_25000 0x9A -#define RF_FDEVMSB_30000 0x01 -#define RF_FDEVLSB_30000 0xEC -#define RF_FDEVMSB_35000 0x02 -#define RF_FDEVLSB_35000 0x3D -#define RF_FDEVMSB_40000 0x02 -#define RF_FDEVLSB_40000 0x8F -#define RF_FDEVMSB_45000 0x02 -#define RF_FDEVLSB_45000 0xE1 -#define RF_FDEVMSB_50000 0x03 -#define RF_FDEVLSB_50000 0x33 -#define RF_FDEVMSB_55000 0x03 -#define RF_FDEVLSB_55000 0x85 -#define RF_FDEVMSB_60000 0x03 -#define RF_FDEVLSB_60000 0xD7 -#define RF_FDEVMSB_65000 0x04 -#define RF_FDEVLSB_65000 0x29 -#define RF_FDEVMSB_70000 0x04 -#define RF_FDEVLSB_70000 0x7B -#define RF_FDEVMSB_75000 0x04 -#define RF_FDEVLSB_75000 0xCD -#define RF_FDEVMSB_80000 0x05 -#define RF_FDEVLSB_80000 0x1F -#define RF_FDEVMSB_85000 0x05 -#define RF_FDEVLSB_85000 0x71 -#define RF_FDEVMSB_90000 0x05 -#define RF_FDEVLSB_90000 0xC3 -#define RF_FDEVMSB_95000 0x06 -#define RF_FDEVLSB_95000 0x14 -#define RF_FDEVMSB_100000 0x06 -#define RF_FDEVLSB_100000 0x66 -#define RF_FDEVMSB_110000 0x07 -#define RF_FDEVLSB_110000 0x0A -#define RF_FDEVMSB_120000 0x07 -#define RF_FDEVLSB_120000 0xAE -#define RF_FDEVMSB_130000 0x08 -#define RF_FDEVLSB_130000 0x52 -#define RF_FDEVMSB_140000 0x08 -#define RF_FDEVLSB_140000 0xF6 -#define RF_FDEVMSB_150000 0x09 -#define RF_FDEVLSB_150000 0x9A -#define RF_FDEVMSB_160000 0x0A -#define RF_FDEVLSB_160000 0x3D -#define RF_FDEVMSB_170000 0x0A -#define RF_FDEVLSB_170000 0xE1 -#define RF_FDEVMSB_180000 0x0B -#define RF_FDEVLSB_180000 0x85 -#define RF_FDEVMSB_190000 0x0C -#define RF_FDEVLSB_190000 0x29 -#define RF_FDEVMSB_200000 0x0C -#define RF_FDEVLSB_200000 0xCD -#define RF_FDEVMSB_210000 0x0D -#define RF_FDEVLSB_210000 0x71 -#define RF_FDEVMSB_220000 0x0E -#define RF_FDEVLSB_220000 0x14 -#define RF_FDEVMSB_230000 0x0E -#define RF_FDEVLSB_230000 0xB8 -#define RF_FDEVMSB_240000 0x0F -#define RF_FDEVLSB_240000 0x5C -#define RF_FDEVMSB_250000 0x10 -#define RF_FDEVLSB_250000 0x00 -#define RF_FDEVMSB_260000 0x10 -#define RF_FDEVLSB_260000 0xA4 -#define RF_FDEVMSB_270000 0x11 -#define RF_FDEVLSB_270000 0x48 -#define RF_FDEVMSB_280000 0x11 -#define RF_FDEVLSB_280000 0xEC -#define RF_FDEVMSB_290000 0x12 -#define RF_FDEVLSB_290000 0x8F -#define RF_FDEVMSB_300000 0x13 -#define RF_FDEVLSB_300000 0x33 - - -// RegFrf (MHz) - carrier frequency -// 315Mhz band -#define RF_FRFMSB_314 0x4E -#define RF_FRFMID_314 0x80 -#define RF_FRFLSB_314 0x00 -#define RF_FRFMSB_315 0x4E -#define RF_FRFMID_315 0xC0 -#define RF_FRFLSB_315 0x00 -#define RF_FRFMSB_316 0x4F -#define RF_FRFMID_316 0x00 -#define RF_FRFLSB_316 0x00 -// 433mhz band -#define RF_FRFMSB_433 0x6C -#define RF_FRFMID_433 0x40 -#define RF_FRFLSB_433 0x00 -#define RF_FRFMSB_434 0x6C -#define RF_FRFMID_434 0x80 -#define RF_FRFLSB_434 0x00 -#define RF_FRFMSB_435 0x6C -#define RF_FRFMID_435 0xC0 -#define RF_FRFLSB_435 0x00 -// 868Mhz band -#define RF_FRFMSB_863 0xD7 -#define RF_FRFMID_863 0xC0 -#define RF_FRFLSB_863 0x00 -#define RF_FRFMSB_864 0xD8 -#define RF_FRFMID_864 0x00 -#define RF_FRFLSB_864 0x00 -#define RF_FRFMSB_865 0xD8 -#define RF_FRFMID_865 0x40 -#define RF_FRFLSB_865 0x00 -#define RF_FRFMSB_866 0xD8 -#define RF_FRFMID_866 0x80 -#define RF_FRFLSB_866 0x00 -#define RF_FRFMSB_867 0xD8 -#define RF_FRFMID_867 0xC0 -#define RF_FRFLSB_867 0x00 -#define RF_FRFMSB_868 0xD9 -#define RF_FRFMID_868 0x00 -#define RF_FRFLSB_868 0x00 -#define RF_FRFMSB_869 0xD9 -#define RF_FRFMID_869 0x40 -#define RF_FRFLSB_869 0x00 -#define RF_FRFMSB_870 0xD9 -#define RF_FRFMID_870 0x80 -#define RF_FRFLSB_870 0x00 -// 915Mhz band -#define RF_FRFMSB_902 0xE1 -#define RF_FRFMID_902 0x80 -#define RF_FRFLSB_902 0x00 -#define RF_FRFMSB_903 0xE1 -#define RF_FRFMID_903 0xC0 -#define RF_FRFLSB_903 0x00 -#define RF_FRFMSB_904 0xE2 -#define RF_FRFMID_904 0x00 -#define RF_FRFLSB_904 0x00 -#define RF_FRFMSB_905 0xE2 -#define RF_FRFMID_905 0x40 -#define RF_FRFLSB_905 0x00 -#define RF_FRFMSB_906 0xE2 -#define RF_FRFMID_906 0x80 -#define RF_FRFLSB_906 0x00 -#define RF_FRFMSB_907 0xE2 -#define RF_FRFMID_907 0xC0 -#define RF_FRFLSB_907 0x00 -#define RF_FRFMSB_908 0xE3 -#define RF_FRFMID_908 0x00 -#define RF_FRFLSB_908 0x00 -#define RF_FRFMSB_909 0xE3 -#define RF_FRFMID_909 0x40 -#define RF_FRFLSB_909 0x00 -#define RF_FRFMSB_910 0xE3 -#define RF_FRFMID_910 0x80 -#define RF_FRFLSB_910 0x00 -#define RF_FRFMSB_911 0xE3 -#define RF_FRFMID_911 0xC0 -#define RF_FRFLSB_911 0x00 -#define RF_FRFMSB_912 0xE4 -#define RF_FRFMID_912 0x00 -#define RF_FRFLSB_912 0x00 -#define RF_FRFMSB_913 0xE4 -#define RF_FRFMID_913 0x40 -#define RF_FRFLSB_913 0x00 -#define RF_FRFMSB_914 0xE4 -#define RF_FRFMID_914 0x80 -#define RF_FRFLSB_914 0x00 -#define RF_FRFMSB_915 0xE4 // Default -#define RF_FRFMID_915 0xC0 // Default -#define RF_FRFLSB_915 0x00 // Default -#define RF_FRFMSB_916 0xE5 -#define RF_FRFMID_916 0x00 -#define RF_FRFLSB_916 0x00 -#define RF_FRFMSB_917 0xE5 -#define RF_FRFMID_917 0x40 -#define RF_FRFLSB_917 0x00 -#define RF_FRFMSB_918 0xE5 -#define RF_FRFMID_918 0x80 -#define RF_FRFLSB_918 0x00 -#define RF_FRFMSB_919 0xE5 -#define RF_FRFMID_919 0xC0 -#define RF_FRFLSB_919 0x00 -#define RF_FRFMSB_920 0xE6 -#define RF_FRFMID_920 0x00 -#define RF_FRFLSB_920 0x00 -#define RF_FRFMSB_921 0xE6 -#define RF_FRFMID_921 0x40 -#define RF_FRFLSB_921 0x00 -#define RF_FRFMSB_922 0xE6 -#define RF_FRFMID_922 0x80 -#define RF_FRFLSB_922 0x00 -#define RF_FRFMSB_923 0xE6 -#define RF_FRFMID_923 0xC0 -#define RF_FRFLSB_923 0x00 -#define RF_FRFMSB_924 0xE7 -#define RF_FRFMID_924 0x00 -#define RF_FRFLSB_924 0x00 -#define RF_FRFMSB_925 0xE7 -#define RF_FRFMID_925 0x40 -#define RF_FRFLSB_925 0x00 -#define RF_FRFMSB_926 0xE7 -#define RF_FRFMID_926 0x80 -#define RF_FRFLSB_926 0x00 -#define RF_FRFMSB_927 0xE7 -#define RF_FRFMID_927 0xC0 -#define RF_FRFLSB_927 0x00 -#define RF_FRFMSB_928 0xE8 -#define RF_FRFMID_928 0x00 -#define RF_FRFLSB_928 0x00 - - -// RegOsc1 -#define RF_OSC1_RCCAL_START 0x80 -#define RF_OSC1_RCCAL_DONE 0x40 - - -// RegAfcCtrl -#define RF_AFCCTRL_LOWBETA_OFF 0x00 // Default -#define RF_AFCCTRL_LOWBETA_ON 0x20 - - -// RegLowBat -#define RF_LOWBAT_MONITOR 0x10 -#define RF_LOWBAT_ON 0x08 -#define RF_LOWBAT_OFF 0x00 // Default - -#define RF_LOWBAT_TRIM_1695 0x00 -#define RF_LOWBAT_TRIM_1764 0x01 -#define RF_LOWBAT_TRIM_1835 0x02 // Default -#define RF_LOWBAT_TRIM_1905 0x03 -#define RF_LOWBAT_TRIM_1976 0x04 -#define RF_LOWBAT_TRIM_2045 0x05 -#define RF_LOWBAT_TRIM_2116 0x06 -#define RF_LOWBAT_TRIM_2185 0x07 - - -// RegListen1 -#define RF_LISTEN1_RESOL_64 0x50 -#define RF_LISTEN1_RESOL_4100 0xA0 // Default -#define RF_LISTEN1_RESOL_262000 0xF0 - -#define RF_LISTEN1_RESOL_IDLE_64 0x40 -#define RF_LISTEN1_RESOL_IDLE_4100 0x80 // Default -#define RF_LISTEN1_RESOL_IDLE_262000 0xC0 - -#define RF_LISTEN1_RESOL_RX_64 0x10 -#define RF_LISTEN1_RESOL_RX_4100 0x20 // Default -#define RF_LISTEN1_RESOL_RX_262000 0x30 - -#define RF_LISTEN1_CRITERIA_RSSI 0x00 // Default -#define RF_LISTEN1_CRITERIA_RSSIANDSYNC 0x08 - -#define RF_LISTEN1_END_00 0x00 -#define RF_LISTEN1_END_01 0x02 // Default -#define RF_LISTEN1_END_10 0x04 - - -// RegListen2 -#define RF_LISTEN2_COEFIDLE_VALUE 0xF5 // Default - - -// RegListen3 -#define RF_LISTEN3_COEFRX_VALUE 0x20 // Default - - -// RegVersion -#define RF_VERSION_VER 0x24 // Default - - -// RegPaLevel -#define RF_PALEVEL_PA0_ON 0x80 // Default -#define RF_PALEVEL_PA0_OFF 0x00 -#define RF_PALEVEL_PA1_ON 0x40 -#define RF_PALEVEL_PA1_OFF 0x00 // Default -#define RF_PALEVEL_PA2_ON 0x20 -#define RF_PALEVEL_PA2_OFF 0x00 // Default - -#define RF_PALEVEL_OUTPUTPOWER_00000 0x00 -#define RF_PALEVEL_OUTPUTPOWER_00001 0x01 -#define RF_PALEVEL_OUTPUTPOWER_00010 0x02 -#define RF_PALEVEL_OUTPUTPOWER_00011 0x03 -#define RF_PALEVEL_OUTPUTPOWER_00100 0x04 -#define RF_PALEVEL_OUTPUTPOWER_00101 0x05 -#define RF_PALEVEL_OUTPUTPOWER_00110 0x06 -#define RF_PALEVEL_OUTPUTPOWER_00111 0x07 -#define RF_PALEVEL_OUTPUTPOWER_01000 0x08 -#define RF_PALEVEL_OUTPUTPOWER_01001 0x09 -#define RF_PALEVEL_OUTPUTPOWER_01010 0x0A -#define RF_PALEVEL_OUTPUTPOWER_01011 0x0B -#define RF_PALEVEL_OUTPUTPOWER_01100 0x0C -#define RF_PALEVEL_OUTPUTPOWER_01101 0x0D -#define RF_PALEVEL_OUTPUTPOWER_01110 0x0E -#define RF_PALEVEL_OUTPUTPOWER_01111 0x0F -#define RF_PALEVEL_OUTPUTPOWER_10000 0x10 -#define RF_PALEVEL_OUTPUTPOWER_10001 0x11 -#define RF_PALEVEL_OUTPUTPOWER_10010 0x12 -#define RF_PALEVEL_OUTPUTPOWER_10011 0x13 -#define RF_PALEVEL_OUTPUTPOWER_10100 0x14 -#define RF_PALEVEL_OUTPUTPOWER_10101 0x15 -#define RF_PALEVEL_OUTPUTPOWER_10110 0x16 -#define RF_PALEVEL_OUTPUTPOWER_10111 0x17 -#define RF_PALEVEL_OUTPUTPOWER_11000 0x18 -#define RF_PALEVEL_OUTPUTPOWER_11001 0x19 -#define RF_PALEVEL_OUTPUTPOWER_11010 0x1A -#define RF_PALEVEL_OUTPUTPOWER_11011 0x1B -#define RF_PALEVEL_OUTPUTPOWER_11100 0x1C -#define RF_PALEVEL_OUTPUTPOWER_11101 0x1D -#define RF_PALEVEL_OUTPUTPOWER_11110 0x1E -#define RF_PALEVEL_OUTPUTPOWER_11111 0x1F // Default - - -// RegPaRamp -#define RF_PARAMP_3400 0x00 -#define RF_PARAMP_2000 0x01 -#define RF_PARAMP_1000 0x02 -#define RF_PARAMP_500 0x03 -#define RF_PARAMP_250 0x04 -#define RF_PARAMP_125 0x05 -#define RF_PARAMP_100 0x06 -#define RF_PARAMP_62 0x07 -#define RF_PARAMP_50 0x08 -#define RF_PARAMP_40 0x09 // Default -#define RF_PARAMP_31 0x0A -#define RF_PARAMP_25 0x0B -#define RF_PARAMP_20 0x0C -#define RF_PARAMP_15 0x0D -#define RF_PARAMP_12 0x0E -#define RF_PARAMP_10 0x0F - - -// RegOcp -#define RF_OCP_OFF 0x0F -#define RF_OCP_ON 0x1A // Default - -#define RF_OCP_TRIM_45 0x00 -#define RF_OCP_TRIM_50 0x01 -#define RF_OCP_TRIM_55 0x02 -#define RF_OCP_TRIM_60 0x03 -#define RF_OCP_TRIM_65 0x04 -#define RF_OCP_TRIM_70 0x05 -#define RF_OCP_TRIM_75 0x06 -#define RF_OCP_TRIM_80 0x07 -#define RF_OCP_TRIM_85 0x08 -#define RF_OCP_TRIM_90 0x09 -#define RF_OCP_TRIM_95 0x0A // Default -#define RF_OCP_TRIM_100 0x0B -#define RF_OCP_TRIM_105 0x0C -#define RF_OCP_TRIM_110 0x0D -#define RF_OCP_TRIM_115 0x0E -#define RF_OCP_TRIM_120 0x0F - - -// RegAgcRef - not present on RFM69/SX1231 -#define RF_AGCREF_AUTO_ON 0x40 // Default -#define RF_AGCREF_AUTO_OFF 0x00 - -#define RF_AGCREF_LEVEL_MINUS80 0x00 // Default -#define RF_AGCREF_LEVEL_MINUS81 0x01 -#define RF_AGCREF_LEVEL_MINUS82 0x02 -#define RF_AGCREF_LEVEL_MINUS83 0x03 -#define RF_AGCREF_LEVEL_MINUS84 0x04 -#define RF_AGCREF_LEVEL_MINUS85 0x05 -#define RF_AGCREF_LEVEL_MINUS86 0x06 -#define RF_AGCREF_LEVEL_MINUS87 0x07 -#define RF_AGCREF_LEVEL_MINUS88 0x08 -#define RF_AGCREF_LEVEL_MINUS89 0x09 -#define RF_AGCREF_LEVEL_MINUS90 0x0A -#define RF_AGCREF_LEVEL_MINUS91 0x0B -#define RF_AGCREF_LEVEL_MINUS92 0x0C -#define RF_AGCREF_LEVEL_MINUS93 0x0D -#define RF_AGCREF_LEVEL_MINUS94 0x0E -#define RF_AGCREF_LEVEL_MINUS95 0x0F -#define RF_AGCREF_LEVEL_MINUS96 0x10 -#define RF_AGCREF_LEVEL_MINUS97 0x11 -#define RF_AGCREF_LEVEL_MINUS98 0x12 -#define RF_AGCREF_LEVEL_MINUS99 0x13 -#define RF_AGCREF_LEVEL_MINUS100 0x14 -#define RF_AGCREF_LEVEL_MINUS101 0x15 -#define RF_AGCREF_LEVEL_MINUS102 0x16 -#define RF_AGCREF_LEVEL_MINUS103 0x17 -#define RF_AGCREF_LEVEL_MINUS104 0x18 -#define RF_AGCREF_LEVEL_MINUS105 0x19 -#define RF_AGCREF_LEVEL_MINUS106 0x1A -#define RF_AGCREF_LEVEL_MINUS107 0x1B -#define RF_AGCREF_LEVEL_MINUS108 0x1C -#define RF_AGCREF_LEVEL_MINUS109 0x1D -#define RF_AGCREF_LEVEL_MINUS110 0x1E -#define RF_AGCREF_LEVEL_MINUS111 0x1F -#define RF_AGCREF_LEVEL_MINUS112 0x20 -#define RF_AGCREF_LEVEL_MINUS113 0x21 -#define RF_AGCREF_LEVEL_MINUS114 0x22 -#define RF_AGCREF_LEVEL_MINUS115 0x23 -#define RF_AGCREF_LEVEL_MINUS116 0x24 -#define RF_AGCREF_LEVEL_MINUS117 0x25 -#define RF_AGCREF_LEVEL_MINUS118 0x26 -#define RF_AGCREF_LEVEL_MINUS119 0x27 -#define RF_AGCREF_LEVEL_MINUS120 0x28 -#define RF_AGCREF_LEVEL_MINUS121 0x29 -#define RF_AGCREF_LEVEL_MINUS122 0x2A -#define RF_AGCREF_LEVEL_MINUS123 0x2B -#define RF_AGCREF_LEVEL_MINUS124 0x2C -#define RF_AGCREF_LEVEL_MINUS125 0x2D -#define RF_AGCREF_LEVEL_MINUS126 0x2E -#define RF_AGCREF_LEVEL_MINUS127 0x2F -#define RF_AGCREF_LEVEL_MINUS128 0x30 -#define RF_AGCREF_LEVEL_MINUS129 0x31 -#define RF_AGCREF_LEVEL_MINUS130 0x32 -#define RF_AGCREF_LEVEL_MINUS131 0x33 -#define RF_AGCREF_LEVEL_MINUS132 0x34 -#define RF_AGCREF_LEVEL_MINUS133 0x35 -#define RF_AGCREF_LEVEL_MINUS134 0x36 -#define RF_AGCREF_LEVEL_MINUS135 0x37 -#define RF_AGCREF_LEVEL_MINUS136 0x38 -#define RF_AGCREF_LEVEL_MINUS137 0x39 -#define RF_AGCREF_LEVEL_MINUS138 0x3A -#define RF_AGCREF_LEVEL_MINUS139 0x3B -#define RF_AGCREF_LEVEL_MINUS140 0x3C -#define RF_AGCREF_LEVEL_MINUS141 0x3D -#define RF_AGCREF_LEVEL_MINUS142 0x3E -#define RF_AGCREF_LEVEL_MINUS143 0x3F - - -// RegAgcThresh1 - not present on RFM69/SX1231 -#define RF_AGCTHRESH1_SNRMARGIN_000 0x00 -#define RF_AGCTHRESH1_SNRMARGIN_001 0x20 -#define RF_AGCTHRESH1_SNRMARGIN_010 0x40 -#define RF_AGCTHRESH1_SNRMARGIN_011 0x60 -#define RF_AGCTHRESH1_SNRMARGIN_100 0x80 -#define RF_AGCTHRESH1_SNRMARGIN_101 0xA0 // Default -#define RF_AGCTHRESH1_SNRMARGIN_110 0xC0 -#define RF_AGCTHRESH1_SNRMARGIN_111 0xE0 - -#define RF_AGCTHRESH1_STEP1_0 0x00 -#define RF_AGCTHRESH1_STEP1_1 0x01 -#define RF_AGCTHRESH1_STEP1_2 0x02 -#define RF_AGCTHRESH1_STEP1_3 0x03 -#define RF_AGCTHRESH1_STEP1_4 0x04 -#define RF_AGCTHRESH1_STEP1_5 0x05 -#define RF_AGCTHRESH1_STEP1_6 0x06 -#define RF_AGCTHRESH1_STEP1_7 0x07 -#define RF_AGCTHRESH1_STEP1_8 0x08 -#define RF_AGCTHRESH1_STEP1_9 0x09 -#define RF_AGCTHRESH1_STEP1_10 0x0A -#define RF_AGCTHRESH1_STEP1_11 0x0B -#define RF_AGCTHRESH1_STEP1_12 0x0C -#define RF_AGCTHRESH1_STEP1_13 0x0D -#define RF_AGCTHRESH1_STEP1_14 0x0E -#define RF_AGCTHRESH1_STEP1_15 0x0F -#define RF_AGCTHRESH1_STEP1_16 0x10 // Default -#define RF_AGCTHRESH1_STEP1_17 0x11 -#define RF_AGCTHRESH1_STEP1_18 0x12 -#define RF_AGCTHRESH1_STEP1_19 0x13 -#define RF_AGCTHRESH1_STEP1_20 0x14 -#define RF_AGCTHRESH1_STEP1_21 0x15 -#define RF_AGCTHRESH1_STEP1_22 0x16 -#define RF_AGCTHRESH1_STEP1_23 0x17 -#define RF_AGCTHRESH1_STEP1_24 0x18 -#define RF_AGCTHRESH1_STEP1_25 0x19 -#define RF_AGCTHRESH1_STEP1_26 0x1A -#define RF_AGCTHRESH1_STEP1_27 0x1B -#define RF_AGCTHRESH1_STEP1_28 0x1C -#define RF_AGCTHRESH1_STEP1_29 0x1D -#define RF_AGCTHRESH1_STEP1_30 0x1E -#define RF_AGCTHRESH1_STEP1_31 0x1F - - -// RegAgcThresh2 - not present on RFM69/SX1231 -#define RF_AGCTHRESH2_STEP2_0 0x00 -#define RF_AGCTHRESH2_STEP2_1 0x10 -#define RF_AGCTHRESH2_STEP2_2 0x20 -#define RF_AGCTHRESH2_STEP2_3 0x30 // XXX wrong -- Default -#define RF_AGCTHRESH2_STEP2_4 0x40 -#define RF_AGCTHRESH2_STEP2_5 0x50 -#define RF_AGCTHRESH2_STEP2_6 0x60 -#define RF_AGCTHRESH2_STEP2_7 0x70 // default -#define RF_AGCTHRESH2_STEP2_8 0x80 -#define RF_AGCTHRESH2_STEP2_9 0x90 -#define RF_AGCTHRESH2_STEP2_10 0xA0 -#define RF_AGCTHRESH2_STEP2_11 0xB0 -#define RF_AGCTHRESH2_STEP2_12 0xC0 -#define RF_AGCTHRESH2_STEP2_13 0xD0 -#define RF_AGCTHRESH2_STEP2_14 0xE0 -#define RF_AGCTHRESH2_STEP2_15 0xF0 - -#define RF_AGCTHRESH2_STEP3_0 0x00 -#define RF_AGCTHRESH2_STEP3_1 0x01 -#define RF_AGCTHRESH2_STEP3_2 0x02 -#define RF_AGCTHRESH2_STEP3_3 0x03 -#define RF_AGCTHRESH2_STEP3_4 0x04 -#define RF_AGCTHRESH2_STEP3_5 0x05 -#define RF_AGCTHRESH2_STEP3_6 0x06 -#define RF_AGCTHRESH2_STEP3_7 0x07 -#define RF_AGCTHRESH2_STEP3_8 0x08 -#define RF_AGCTHRESH2_STEP3_9 0x09 -#define RF_AGCTHRESH2_STEP3_10 0x0A -#define RF_AGCTHRESH2_STEP3_11 0x0B // Default -#define RF_AGCTHRESH2_STEP3_12 0x0C -#define RF_AGCTHRESH2_STEP3_13 0x0D -#define RF_AGCTHRESH2_STEP3_14 0x0E -#define RF_AGCTHRESH2_STEP3_15 0x0F - - -// RegAgcThresh3 - not present on RFM69/SX1231 -#define RF_AGCTHRESH3_STEP4_0 0x00 -#define RF_AGCTHRESH3_STEP4_1 0x10 -#define RF_AGCTHRESH3_STEP4_2 0x20 -#define RF_AGCTHRESH3_STEP4_3 0x30 -#define RF_AGCTHRESH3_STEP4_4 0x40 -#define RF_AGCTHRESH3_STEP4_5 0x50 -#define RF_AGCTHRESH3_STEP4_6 0x60 -#define RF_AGCTHRESH3_STEP4_7 0x70 -#define RF_AGCTHRESH3_STEP4_8 0x80 -#define RF_AGCTHRESH3_STEP4_9 0x90 // Default -#define RF_AGCTHRESH3_STEP4_10 0xA0 -#define RF_AGCTHRESH3_STEP4_11 0xB0 -#define RF_AGCTHRESH3_STEP4_12 0xC0 -#define RF_AGCTHRESH3_STEP4_13 0xD0 -#define RF_AGCTHRESH3_STEP4_14 0xE0 -#define RF_AGCTHRESH3_STEP4_15 0xF0 - -#define RF_AGCTHRESH3_STEP5_0 0x00 -#define RF_AGCTHRESH3_STEP5_1 0x01 -#define RF_AGCTHRESH3_STEP5_2 0x02 -#define RF_AGCTHRESH3_STEP5_3 0x03 -#define RF_AGCTHRESH3_STEP5_4 0x04 -#define RF_AGCTHRESH3_STEP5_5 0x05 -#define RF_AGCTHRESH3_STEP5_6 0x06 -#define RF_AGCTHRESH3_STEP5_7 0x07 -#define RF_AGCTHRES33_STEP5_8 0x08 -#define RF_AGCTHRESH3_STEP5_9 0x09 -#define RF_AGCTHRESH3_STEP5_10 0x0A -#define RF_AGCTHRESH3_STEP5_11 0x0B // Default -#define RF_AGCTHRESH3_STEP5_12 0x0C -#define RF_AGCTHRESH3_STEP5_13 0x0D -#define RF_AGCTHRESH3_STEP5_14 0x0E -#define RF_AGCTHRESH3_STEP5_15 0x0F - - -// RegLna -#define RF_LNA_ZIN_50 0x00 // Reset value -#define RF_LNA_ZIN_200 0x80 // Recommended default - -#define RF_LNA_LOWPOWER_OFF 0x00 // Default -#define RF_LNA_LOWPOWER_ON 0x40 - -#define RF_LNA_CURRENTGAIN 0x08 - -#define RF_LNA_GAINSELECT_AUTO 0x00 // Default -#define RF_LNA_GAINSELECT_MAX 0x01 -#define RF_LNA_GAINSELECT_MAXMINUS6 0x02 -#define RF_LNA_GAINSELECT_MAXMINUS12 0x03 -#define RF_LNA_GAINSELECT_MAXMINUS24 0x04 -#define RF_LNA_GAINSELECT_MAXMINUS36 0x05 -#define RF_LNA_GAINSELECT_MAXMINUS48 0x06 - - -// RegRxBw -#define RF_RXBW_DCCFREQ_000 0x00 -#define RF_RXBW_DCCFREQ_001 0x20 -#define RF_RXBW_DCCFREQ_010 0x40 // Recommended default -#define RF_RXBW_DCCFREQ_011 0x60 -#define RF_RXBW_DCCFREQ_100 0x80 // Reset value -#define RF_RXBW_DCCFREQ_101 0xA0 -#define RF_RXBW_DCCFREQ_110 0xC0 -#define RF_RXBW_DCCFREQ_111 0xE0 - -#define RF_RXBW_MANT_16 0x00 // Reset value -#define RF_RXBW_MANT_20 0x08 -#define RF_RXBW_MANT_24 0x10 // Recommended default - -#define RF_RXBW_EXP_0 0x00 -#define RF_RXBW_EXP_1 0x01 -#define RF_RXBW_EXP_2 0x02 -#define RF_RXBW_EXP_3 0x03 -#define RF_RXBW_EXP_4 0x04 -#define RF_RXBW_EXP_5 0x05 // Recommended default -#define RF_RXBW_EXP_6 0x06 // Reset value -#define RF_RXBW_EXP_7 0x07 - - -// RegAfcBw -#define RF_AFCBW_DCCFREQAFC_000 0x00 -#define RF_AFCBW_DCCFREQAFC_001 0x20 -#define RF_AFCBW_DCCFREQAFC_010 0x40 -#define RF_AFCBW_DCCFREQAFC_011 0x60 -#define RF_AFCBW_DCCFREQAFC_100 0x80 // Default -#define RF_AFCBW_DCCFREQAFC_101 0xA0 -#define RF_AFCBW_DCCFREQAFC_110 0xC0 -#define RF_AFCBW_DCCFREQAFC_111 0xE0 - -#define RF_AFCBW_MANTAFC_16 0x00 -#define RF_AFCBW_MANTAFC_20 0x08 // Default -#define RF_AFCBW_MANTAFC_24 0x10 - -#define RF_AFCBW_EXPAFC_0 0x00 -#define RF_AFCBW_EXPAFC_1 0x01 -#define RF_AFCBW_EXPAFC_2 0x02 // Reset value -#define RF_AFCBW_EXPAFC_3 0x03 // Recommended default -#define RF_AFCBW_EXPAFC_4 0x04 -#define RF_AFCBW_EXPAFC_5 0x05 -#define RF_AFCBW_EXPAFC_6 0x06 -#define RF_AFCBW_EXPAFC_7 0x07 - - -// RegOokPeak -#define RF_OOKPEAK_THRESHTYPE_FIXED 0x00 -#define RF_OOKPEAK_THRESHTYPE_PEAK 0x40 // Default -#define RF_OOKPEAK_THRESHTYPE_AVERAGE 0x80 - -#define RF_OOKPEAK_PEAKTHRESHSTEP_000 0x00 // Default -#define RF_OOKPEAK_PEAKTHRESHSTEP_001 0x08 -#define RF_OOKPEAK_PEAKTHRESHSTEP_010 0x10 -#define RF_OOKPEAK_PEAKTHRESHSTEP_011 0x18 -#define RF_OOKPEAK_PEAKTHRESHSTEP_100 0x20 -#define RF_OOKPEAK_PEAKTHRESHSTEP_101 0x28 -#define RF_OOKPEAK_PEAKTHRESHSTEP_110 0x30 -#define RF_OOKPEAK_PEAKTHRESHSTEP_111 0x38 - -#define RF_OOKPEAK_PEAKTHRESHDEC_000 0x00 // Default -#define RF_OOKPEAK_PEAKTHRESHDEC_001 0x01 -#define RF_OOKPEAK_PEAKTHRESHDEC_010 0x02 -#define RF_OOKPEAK_PEAKTHRESHDEC_011 0x03 -#define RF_OOKPEAK_PEAKTHRESHDEC_100 0x04 -#define RF_OOKPEAK_PEAKTHRESHDEC_101 0x05 -#define RF_OOKPEAK_PEAKTHRESHDEC_110 0x06 -#define RF_OOKPEAK_PEAKTHRESHDEC_111 0x07 - - -// RegOokAvg -#define RF_OOKAVG_AVERAGETHRESHFILT_00 0x00 -#define RF_OOKAVG_AVERAGETHRESHFILT_01 0x40 -#define RF_OOKAVG_AVERAGETHRESHFILT_10 0x80 // Default -#define RF_OOKAVG_AVERAGETHRESHFILT_11 0xC0 - - -// RegOokFix -#define RF_OOKFIX_FIXEDTHRESH_VALUE 0x06 // Default - - -// RegAfcFei -#define RF_AFCFEI_FEI_DONE 0x40 -#define RF_AFCFEI_FEI_START 0x20 -#define RF_AFCFEI_AFC_DONE 0x10 -#define RF_AFCFEI_AFCAUTOCLEAR_ON 0x08 -#define RF_AFCFEI_AFCAUTOCLEAR_OFF 0x00 // Default - -#define RF_AFCFEI_AFCAUTO_ON 0x04 -#define RF_AFCFEI_AFCAUTO_OFF 0x00 // Default - -#define RF_AFCFEI_AFC_CLEAR 0x02 -#define RF_AFCFEI_AFC_START 0x01 - - -// RegRssiConfig -#define RF_RSSI_FASTRX_ON 0x08 // not present on RFM69/SX1231 -#define RF_RSSI_FASTRX_OFF 0x00 // Default - -#define RF_RSSI_DONE 0x02 -#define RF_RSSI_START 0x01 - - -// RegDioMapping1 -#define RF_DIOMAPPING1_DIO0_00 0x00 // Default -#define RF_DIOMAPPING1_DIO0_01 0x40 -#define RF_DIOMAPPING1_DIO0_10 0x80 -#define RF_DIOMAPPING1_DIO0_11 0xC0 - -#define RF_DIOMAPPING1_DIO1_00 0x00 // Default -#define RF_DIOMAPPING1_DIO1_01 0x10 -#define RF_DIOMAPPING1_DIO1_10 0x20 -#define RF_DIOMAPPING1_DIO1_11 0x30 - -#define RF_DIOMAPPING1_DIO2_00 0x00 // Default -#define RF_DIOMAPPING1_DIO2_01 0x04 -#define RF_DIOMAPPING1_DIO2_10 0x08 -#define RF_DIOMAPPING1_DIO2_11 0x0C - -#define RF_DIOMAPPING1_DIO3_00 0x00 // Default -#define RF_DIOMAPPING1_DIO3_01 0x01 -#define RF_DIOMAPPING1_DIO3_10 0x02 -#define RF_DIOMAPPING1_DIO3_11 0x03 - - -// RegDioMapping2 -#define RF_DIOMAPPING2_DIO4_00 0x00 // Default -#define RF_DIOMAPPING2_DIO4_01 0x40 -#define RF_DIOMAPPING2_DIO4_10 0x80 -#define RF_DIOMAPPING2_DIO4_11 0xC0 - -#define RF_DIOMAPPING2_DIO5_00 0x00 // Default -#define RF_DIOMAPPING2_DIO5_01 0x10 -#define RF_DIOMAPPING2_DIO5_10 0x20 -#define RF_DIOMAPPING2_DIO5_11 0x30 - -#define RF_DIOMAPPING2_CLKOUT_32 0x00 -#define RF_DIOMAPPING2_CLKOUT_16 0x01 -#define RF_DIOMAPPING2_CLKOUT_8 0x02 -#define RF_DIOMAPPING2_CLKOUT_4 0x03 -#define RF_DIOMAPPING2_CLKOUT_2 0x04 -#define RF_DIOMAPPING2_CLKOUT_1 0x05 // Reset value -#define RF_DIOMAPPING2_CLKOUT_RC 0x06 -#define RF_DIOMAPPING2_CLKOUT_OFF 0x07 // Recommended default - - -// RegIrqFlags1 -#define RF_IRQFLAGS1_MODEREADY 0x80 -#define RF_IRQFLAGS1_RXREADY 0x40 -#define RF_IRQFLAGS1_TXREADY 0x20 -#define RF_IRQFLAGS1_PLLLOCK 0x10 -#define RF_IRQFLAGS1_RSSI 0x08 -#define RF_IRQFLAGS1_TIMEOUT 0x04 -#define RF_IRQFLAGS1_AUTOMODE 0x02 -#define RF_IRQFLAGS1_SYNCADDRESSMATCH 0x01 - - -// RegIrqFlags2 -#define RF_IRQFLAGS2_FIFOFULL 0x80 -#define RF_IRQFLAGS2_FIFONOTEMPTY 0x40 -#define RF_IRQFLAGS2_FIFOLEVEL 0x20 -#define RF_IRQFLAGS2_FIFOOVERRUN 0x10 -#define RF_IRQFLAGS2_PACKETSENT 0x08 -#define RF_IRQFLAGS2_PAYLOADREADY 0x04 -#define RF_IRQFLAGS2_CRCOK 0x02 -#define RF_IRQFLAGS2_LOWBAT 0x01 // not present on RFM69/SX1231 - - -// RegRssiThresh -#define RF_RSSITHRESH_VALUE 0xE4 // Default - - -// RegRxTimeout1 -#define RF_RXTIMEOUT1_RXSTART_VALUE 0x00 // Default - - -// RegRxTimeout2 -#define RF_RXTIMEOUT2_RSSITHRESH_VALUE 0x00 // Default - - -// RegPreamble -#define RF_PREAMBLESIZE_MSB_VALUE 0x00 // Default -#define RF_PREAMBLESIZE_LSB_VALUE 0x03 // Default - - -// RegSyncConfig -#define RF_SYNC_ON 0x80 // Default -#define RF_SYNC_OFF 0x00 - -#define RF_SYNC_FIFOFILL_AUTO 0x00 // Default -- when sync interrupt occurs -#define RF_SYNC_FIFOFILL_MANUAL 0x40 - -#define RF_SYNC_SIZE_1 0x00 -#define RF_SYNC_SIZE_2 0x08 -#define RF_SYNC_SIZE_3 0x10 -#define RF_SYNC_SIZE_4 0x18 // Default -#define RF_SYNC_SIZE_5 0x20 -#define RF_SYNC_SIZE_6 0x28 -#define RF_SYNC_SIZE_7 0x30 -#define RF_SYNC_SIZE_8 0x38 - -#define RF_SYNC_TOL_0 0x00 // Default -#define RF_SYNC_TOL_1 0x01 -#define RF_SYNC_TOL_2 0x02 -#define RF_SYNC_TOL_3 0x03 -#define RF_SYNC_TOL_4 0x04 -#define RF_SYNC_TOL_5 0x05 -#define RF_SYNC_TOL_6 0x06 -#define RF_SYNC_TOL_7 0x07 - - -// RegSyncValue1-8 -#define RF_SYNC_BYTE1_VALUE 0x00 // Default -#define RF_SYNC_BYTE2_VALUE 0x00 // Default -#define RF_SYNC_BYTE3_VALUE 0x00 // Default -#define RF_SYNC_BYTE4_VALUE 0x00 // Default -#define RF_SYNC_BYTE5_VALUE 0x00 // Default -#define RF_SYNC_BYTE6_VALUE 0x00 // Default -#define RF_SYNC_BYTE7_VALUE 0x00 // Default -#define RF_SYNC_BYTE8_VALUE 0x00 // Default - - -// RegPacketConfig1 -#define RF_PACKET1_FORMAT_FIXED 0x00 // Default -#define RF_PACKET1_FORMAT_VARIABLE 0x80 - -#define RF_PACKET1_DCFREE_OFF 0x00 // Default -#define RF_PACKET1_DCFREE_MANCHESTER 0x20 -#define RF_PACKET1_DCFREE_WHITENING 0x40 - -#define RF_PACKET1_CRC_ON 0x10 // Default -#define RF_PACKET1_CRC_OFF 0x00 - -#define RF_PACKET1_CRCAUTOCLEAR_ON 0x00 // Default -#define RF_PACKET1_CRCAUTOCLEAR_OFF 0x08 - -#define RF_PACKET1_ADRSFILTERING_OFF 0x00 // Default -#define RF_PACKET1_ADRSFILTERING_NODE 0x02 -#define RF_PACKET1_ADRSFILTERING_NODEBROADCAST 0x04 - - -// RegPayloadLength -#define RF_PAYLOADLENGTH_VALUE 0x40 // Default - - -// RegBroadcastAdrs -#define RF_BROADCASTADDRESS_VALUE 0x00 - - -// RegAutoModes -#define RF_AUTOMODES_ENTER_OFF 0x00 // Default -#define RF_AUTOMODES_ENTER_FIFONOTEMPTY 0x20 -#define RF_AUTOMODES_ENTER_FIFOLEVEL 0x40 -#define RF_AUTOMODES_ENTER_CRCOK 0x60 -#define RF_AUTOMODES_ENTER_PAYLOADREADY 0x80 -#define RF_AUTOMODES_ENTER_SYNCADRSMATCH 0xA0 -#define RF_AUTOMODES_ENTER_PACKETSENT 0xC0 -#define RF_AUTOMODES_ENTER_FIFOEMPTY 0xE0 - -#define RF_AUTOMODES_EXIT_OFF 0x00 // Default -#define RF_AUTOMODES_EXIT_FIFOEMPTY 0x04 -#define RF_AUTOMODES_EXIT_FIFOLEVEL 0x08 -#define RF_AUTOMODES_EXIT_CRCOK 0x0C -#define RF_AUTOMODES_EXIT_PAYLOADREADY 0x10 -#define RF_AUTOMODES_EXIT_SYNCADRSMATCH 0x14 -#define RF_AUTOMODES_EXIT_PACKETSENT 0x18 -#define RF_AUTOMODES_EXIT_RXTIMEOUT 0x1C - -#define RF_AUTOMODES_INTERMEDIATE_SLEEP 0x00 // Default -#define RF_AUTOMODES_INTERMEDIATE_STANDBY 0x01 -#define RF_AUTOMODES_INTERMEDIATE_RECEIVER 0x02 -#define RF_AUTOMODES_INTERMEDIATE_TRANSMITTER 0x03 - - -// RegFifoThresh -#define RF_FIFOTHRESH_TXSTART_FIFOTHRESH 0x00 // Reset value -#define RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY 0x80 // Recommended default - -#define RF_FIFOTHRESH_VALUE 0x0F // Default - - -// RegPacketConfig2 -#define RF_PACKET2_RXRESTARTDELAY_1BIT 0x00 // Default -#define RF_PACKET2_RXRESTARTDELAY_2BITS 0x10 -#define RF_PACKET2_RXRESTARTDELAY_4BITS 0x20 -#define RF_PACKET2_RXRESTARTDELAY_8BITS 0x30 -#define RF_PACKET2_RXRESTARTDELAY_16BITS 0x40 -#define RF_PACKET2_RXRESTARTDELAY_32BITS 0x50 -#define RF_PACKET2_RXRESTARTDELAY_64BITS 0x60 -#define RF_PACKET2_RXRESTARTDELAY_128BITS 0x70 -#define RF_PACKET2_RXRESTARTDELAY_256BITS 0x80 -#define RF_PACKET2_RXRESTARTDELAY_512BITS 0x90 -#define RF_PACKET2_RXRESTARTDELAY_1024BITS 0xA0 -#define RF_PACKET2_RXRESTARTDELAY_2048BITS 0xB0 -#define RF_PACKET2_RXRESTARTDELAY_NONE 0xC0 -#define RF_PACKET2_RXRESTART 0x04 - -#define RF_PACKET2_AUTORXRESTART_ON 0x02 // Default -#define RF_PACKET2_AUTORXRESTART_OFF 0x00 - -#define RF_PACKET2_AES_ON 0x01 -#define RF_PACKET2_AES_OFF 0x00 // Default - - -// RegAesKey1-16 -#define RF_AESKEY1_VALUE 0x00 // Default -#define RF_AESKEY2_VALUE 0x00 // Default -#define RF_AESKEY3_VALUE 0x00 // Default -#define RF_AESKEY4_VALUE 0x00 // Default -#define RF_AESKEY5_VALUE 0x00 // Default -#define RF_AESKEY6_VALUE 0x00 // Default -#define RF_AESKEY7_VALUE 0x00 // Default -#define RF_AESKEY8_VALUE 0x00 // Default -#define RF_AESKEY9_VALUE 0x00 // Default -#define RF_AESKEY10_VALUE 0x00 // Default -#define RF_AESKEY11_VALUE 0x00 // Default -#define RF_AESKEY12_VALUE 0x00 // Default -#define RF_AESKEY13_VALUE 0x00 // Default -#define RF_AESKEY14_VALUE 0x00 // Default -#define RF_AESKEY15_VALUE 0x00 // Default -#define RF_AESKEY16_VALUE 0x00 // Default - - -// RegTemp1 -#define RF_TEMP1_MEAS_START 0x08 -#define RF_TEMP1_MEAS_RUNNING 0x04 -// not present on RFM69/SX1231 -#define RF_TEMP1_ADCLOWPOWER_ON 0x01 // Default -#define RF_TEMP1_ADCLOWPOWER_OFF 0x00 - - -// RegTestLna -#define RF_TESTLNA_NORMAL 0x1B -#define RF_TESTLNA_HIGH_SENSITIVITY 0x2D - - -// RegTestDagc -#define RF_DAGC_NORMAL 0x00 // Reset value -#define RF_DAGC_IMPROVED_LOWBETA1 0x20 -#define RF_DAGC_IMPROVED_LOWBETA0 0x30 // Recommended default diff --git a/lib/MySensors/hal/transport/RFM95/MyTransportRFM95.cpp b/lib/MySensors/hal/transport/RFM95/MyTransportRFM95.cpp deleted file mode 100644 index 3d5bfdc8..00000000 --- a/lib/MySensors/hal/transport/RFM95/MyTransportRFM95.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "hal/transport/RFM95/driver/RFM95.h" - -bool transportInit(void) -{ - const bool result = RFM95_initialise(MY_RFM95_FREQUENCY); -#if defined(MY_RFM95_TCXO) - RFM95_enableTCXO(); -#endif -#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM95_ATC_MODE_DISABLED) - // only enable ATC mode in nodes - RFM95_ATCmode(true, MY_RFM95_ATC_TARGET_RSSI); -#endif - return result; -} - -void transportSetAddress(const uint8_t address) -{ - RFM95_setAddress(address); -} - -uint8_t transportGetAddress(void) -{ - return RFM95_getAddress(); -} - -bool transportSend(const uint8_t to, const void *data, const uint8_t len, const bool noACK) -{ - return RFM95_sendWithRetry(to, data, len, noACK); -} - -bool transportDataAvailable(void) -{ - RFM95_handler(); - return RFM95_available(); -} - -bool transportSanityCheck(void) -{ - return RFM95_sanityCheck(); -} - -uint8_t transportReceive(void *data) -{ - uint8_t len = RFM95_receive((uint8_t *)data, MAX_MESSAGE_SIZE); - return len; -} - -void transportSleep(void) -{ - (void)RFM95_sleep(); -} - -void transportStandBy(void) -{ - (void)RFM95_standBy(); -} - -void transportPowerDown(void) -{ - RFM95_powerDown(); -} - -void transportPowerUp(void) -{ - RFM95_powerUp(); -} - -void transportToggleATCmode(const bool OnOff, const int16_t targetRSSI) -{ - RFM95_ATCmode(OnOff, targetRSSI); -} - -int16_t transportGetSendingRSSI(void) -{ - return RFM95_getSendingRSSI(); -} - -int16_t transportGetReceivingRSSI(void) -{ - return RFM95_getReceivingRSSI(); -} - -int16_t transportGetSendingSNR(void) -{ - return RFM95_getSendingSNR(); -} - -int16_t transportGetReceivingSNR(void) -{ - return RFM95_getReceivingSNR(); -} - -int16_t transportGetTxPowerPercent(void) -{ - return RFM95_getTxPowerPercent(); -} - -int16_t transportGetTxPowerLevel(void) -{ - return RFM95_getTxPowerLevel(); -} - -bool transportSetTxPowerPercent(const uint8_t powerPercent) -{ - return RFM95_setTxPowerPercent(powerPercent); -} - diff --git a/lib/MySensors/hal/transport/RFM95/driver/RFM95.cpp b/lib/MySensors/hal/transport/RFM95/driver/RFM95.cpp deleted file mode 100644 index aa40b57f..00000000 --- a/lib/MySensors/hal/transport/RFM95/driver/RFM95.cpp +++ /dev/null @@ -1,685 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on Mike McCauley's RFM95 library, Copyright (C) 2014 Mike McCauley - * Radiohead http://www.airspayce.com/mikem/arduino/RadioHead/index.html - * - * RFM95 driver refactored and optimized for MySensors, Copyright (C) 2017-2018 Olivier Mauti - * - * Definitions for HopeRF LoRa radios: - * http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf - * - */ - -#include "RFM95.h" - -// debug -#if defined(MY_DEBUG_VERBOSE_RFM95) -#define RFM95_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< Debug print -#else -#define RFM95_DEBUG(x,...) //!< DEBUG null -#endif - -rfm95_internal_t RFM95; //!< internal variables -volatile uint8_t RFM95_irq; //(externalRSSI + RFM95_RSSI_OFFSET); -} - -LOCAL inline int16_t RFM95_internalToRSSI(const rfm95_RSSI_t internalRSSI) -{ - return static_cast(internalRSSI - RFM95_RSSI_OFFSET); -} - -LOCAL bool RFM95_initialise(const uint32_t frequencyHz) -{ - RFM95_DEBUG(PSTR("RFM95:INIT\n")); - // power pin, if defined -#if defined(MY_RFM95_POWER_PIN) - hwPinMode(MY_RFM95_POWER_PIN, OUTPUT); -#endif - RFM95_powerUp(); - // reset radio module if rst pin defined -#if defined(MY_RFM95_RST_PIN) - hwPinMode(MY_RFM95_RST_PIN, OUTPUT); - hwDigitalWrite(MY_RFM95_RST_PIN, LOW); - // 100uS - delayMicroseconds(RFM95_POWERUP_DELAY_MS); - hwDigitalWrite(MY_RFM95_RST_PIN, HIGH); - // wait until chip ready - delay(5); - RFM95_DEBUG(PSTR("RFM95:INIT:PIN,CS=%" PRIu8 ",IQP=%" PRIu8 ",IQN=%" PRIu8 ",RST=%" PRIu8 "\n"), - MY_RFM95_CS_PIN, MY_RFM95_IRQ_PIN, - MY_RFM95_IRQ_NUM,MY_RFM95_RST_PIN); -#else - RFM95_DEBUG(PSTR("RFM95:INIT:PIN,CS=%" PRIu8 ",IQP=%" PRIu8 ",IQN=%" PRIu8 "\n"), MY_RFM95_CS_PIN, - MY_RFM95_IRQ_PIN, - MY_RFM95_IRQ_NUM); -#endif - - // set variables - RFM95.address = RFM95_BROADCAST_ADDRESS; - RFM95.ackReceived = false; - RFM95.dataReceived = false; - RFM95.txSequenceNumber = 0; // initialise TX sequence counter - RFM95.powerLevel = 0; - RFM95.ATCenabled = false; - RFM95.ATCtargetRSSI = RFM95_RSSItoInternal(RFM95_TARGET_RSSI); - - // SPI init -#if !defined(__linux__) - hwDigitalWrite(MY_RFM95_CS_PIN, HIGH); - hwPinMode(MY_RFM95_CS_PIN, OUTPUT); -#endif - RFM95_SPI.begin(); - - // Set LoRa mode (during sleep mode) - (void)RFM95_writeReg(RFM95_REG_01_OP_MODE, RFM95_MODE_SLEEP | RFM95_LONG_RANGE_MODE); - delay(10); // Wait for sleep mode to take over - - // TCXO init, if present -#if defined(MY_RFM95_TCXO) - RFM95_enableTCXO(); -#else - (void)RFM95_enableTCXO; -#endif - - // Set up FIFO, 256 bytes: LoRa max message 64 bytes, set half RX half TX (default) - (void)RFM95_writeReg(RFM95_REG_0F_FIFO_RX_BASE_ADDR, RFM95_RX_FIFO_ADDR); - (void)RFM95_writeReg(RFM95_REG_0E_FIFO_TX_BASE_ADDR, RFM95_TX_FIFO_ADDR); - (void)RFM95_writeReg(RFM95_REG_23_MAX_PAYLOAD_LENGTH, RFM95_MAX_PACKET_LEN); - - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); - const rfm95_modemConfig_t configuration = { MY_RFM95_MODEM_CONFIGRUATION }; - RFM95_setModemRegisters(&configuration); - RFM95_setPreambleLength(RFM95_PREAMBLE_LENGTH); - RFM95_setFrequency(frequencyHz); - (void)RFM95_setTxPowerLevel(MY_RFM95_TX_POWER_DBM); - - if (!RFM95_sanityCheck()) { - // sanity check failed, check wiring or replace module - RFM95_DEBUG(PSTR("!RFM95:INIT:SANCHK FAIL\n")); - return false; - } - - // IRQ - RFM95_irq = false; - hwPinMode(MY_RFM95_IRQ_PIN, INPUT); - attachInterrupt(MY_RFM95_IRQ_NUM, RFM95_interruptHandler, RISING); - return true; -} - -LOCAL void IRQ_HANDLER_ATTR RFM95_interruptHandler(void) -{ - // set flag - RFM95_irq = true; -} - -// RxDone, TxDone, CADDone is mapped to DI0 -LOCAL void RFM95_interruptHandling(void) -{ - // read interrupt register - const uint8_t irqFlags = RFM95_readReg(RFM95_REG_12_IRQ_FLAGS); - if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & RFM95_RX_DONE)) { - // RXSingle mode: Radio goes automatically to STDBY after packet received - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); - // Check CRC flag - if (!(irqFlags & RFM95_PAYLOAD_CRC_ERROR)) { - const uint8_t bufLen = min(RFM95_readReg(RFM95_REG_13_RX_NB_BYTES), (uint8_t)RFM95_MAX_PACKET_LEN); - if (bufLen >= RFM95_HEADER_LEN) { - // Reset the fifo read ptr to the beginning of the packet - (void)RFM95_writeReg(RFM95_REG_0D_FIFO_ADDR_PTR, RFM95_readReg(RFM95_REG_10_FIFO_RX_CURRENT_ADDR)); - (void)RFM95_burstReadReg(RFM95_REG_00_FIFO, RFM95.currentPacket.data, bufLen); - RFM95.currentPacket.RSSI = static_cast(RFM95_readReg( - RFM95_REG_1A_PKT_RSSI_VALUE)); // RSSI of latest packet received - RFM95.currentPacket.SNR = static_cast(RFM95_readReg(RFM95_REG_19_PKT_SNR_VALUE)); - RFM95.currentPacket.payloadLen = bufLen - RFM95_HEADER_LEN; - if ((RFM95.currentPacket.header.version >= RFM95_MIN_PACKET_HEADER_VERSION) && - (RFM95_PROMISCUOUS || RFM95.currentPacket.header.recipient == RFM95.address || - RFM95.currentPacket.header.recipient == RFM95_BROADCAST_ADDRESS)) { - // Message for us - RFM95.ackReceived = RFM95_getACKReceived(RFM95.currentPacket.header.controlFlags) && - !RFM95_getACKRequested(RFM95.currentPacket.header.controlFlags); - RFM95.dataReceived = !RFM95.ackReceived; - } - } - } else { - // CRC error - RFM95_DEBUG(PSTR("!RFM95:IRH:CRC ERROR\n")); - // FIFO is cleared when switch from STDBY to RX or TX - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_RX); - } - } else if (RFM95.radioMode == RFM95_RADIO_MODE_TX && (irqFlags & RFM95_TX_DONE) ) { - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_RX); - } else if (RFM95.radioMode == RFM95_RADIO_MODE_CAD && (irqFlags & RFM95_CAD_DONE) ) { - RFM95.channelActive = irqFlags & RFM95_CAD_DETECTED; - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); - } - // Clear IRQ flags - RFM95_writeReg(RFM95_REG_12_IRQ_FLAGS, RFM95_CLEAR_IRQ); -} - -LOCAL void RFM95_handler(void) -{ - if (RFM95_irq) { - RFM95_irq = false; - RFM95_interruptHandling(); - } -} - -LOCAL bool RFM95_available(void) -{ - if (RFM95.dataReceived) { - // data received - we are still in STDBY from IRQ handler - return true; - } else if (RFM95.radioMode == RFM95_RADIO_MODE_TX) { - return false; - } else if (RFM95.radioMode != RFM95_RADIO_MODE_RX) { - // we are not in RX, not CAD, and no data received - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_RX); - } - return false; -} - -LOCAL uint8_t RFM95_receive(uint8_t *buf, const uint8_t maxBufSize) -{ - const uint8_t payloadLen = min(RFM95.currentPacket.payloadLen, maxBufSize); - const uint8_t sender = RFM95.currentPacket.header.sender; - const rfm95_sequenceNumber_t sequenceNumber = RFM95.currentPacket.header.sequenceNumber; - const rfm95_controlFlags_t controlFlags = RFM95.currentPacket.header.controlFlags; - const rfm95_RSSI_t RSSI = RFM95.currentPacket.RSSI; - const rfm95_SNR_t SNR = RFM95.currentPacket.SNR; - if (buf != NULL) { - (void)memcpy((void *)buf, (void *)&RFM95.currentPacket.payload, payloadLen); - } - // clear data flag - RFM95.dataReceived = false; - // ACK handling - if (RFM95_getACKRequested(controlFlags) && !RFM95_getACKReceived(controlFlags)) { -#if defined(MY_GATEWAY_FEATURE) && (F_CPU>16*1000000ul) - // delay for fast GW and slow nodes - delay(50); -#endif - RFM95_sendACK(sender, sequenceNumber, RSSI, SNR); - } - return payloadLen; -} - -LOCAL bool RFM95_sendFrame(rfm95_packet_t *packet, const bool increaseSequenceCounter) -{ - // Check channel activity - if (!RFM95_waitCAD()) { - return false; - } - // radio is in STDBY - if (increaseSequenceCounter) { - // increase sequence counter, overflow is ok - RFM95.txSequenceNumber++; - } - packet->header.sequenceNumber = RFM95.txSequenceNumber; - // Position at the beginning of the TX FIFO - (void)RFM95_writeReg(RFM95_REG_0D_FIFO_ADDR_PTR, RFM95_TX_FIFO_ADDR); - // write packet - const uint8_t finalLen = packet->payloadLen + RFM95_HEADER_LEN; - (void)RFM95_burstWriteReg(RFM95_REG_00_FIFO, packet->data, finalLen); - // total payload length - (void)RFM95_writeReg(RFM95_REG_22_PAYLOAD_LENGTH, finalLen); - // send message, if sent, irq fires and radio returns to standby - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_TX); - // wait until IRQ fires or timeout - const uint32_t startTX_MS = hwMillis(); - // todo: make this payload length + bit rate dependend - while (!RFM95_irq && (hwMillis() - startTX_MS < MY_RFM95_TX_TIMEOUT_MS) ) { - doYield(); - } - return RFM95_irq; -} - -LOCAL bool RFM95_send(const uint8_t recipient, uint8_t *data, const uint8_t len, - const rfm95_controlFlags_t flags, const bool increaseSequenceCounter) -{ - rfm95_packet_t packet; - packet.header.version = RFM95_PACKET_HEADER_VERSION; - packet.header.sender = RFM95.address; - packet.header.recipient = recipient; - packet.payloadLen = min(len, (uint8_t)RFM95_MAX_PAYLOAD_LEN); - packet.header.controlFlags = flags; - (void)memcpy((void *)&packet.payload, (void *)data, packet.payloadLen); - return RFM95_sendFrame(&packet, increaseSequenceCounter); -} - -LOCAL void RFM95_setFrequency(const uint32_t frequencyHz) -{ - const uint32_t freqReg = (uint32_t)(frequencyHz / RFM95_FSTEP); - (void)RFM95_writeReg(RFM95_REG_06_FRF_MSB, (uint8_t)((freqReg >> 16) & 0xff)); - (void)RFM95_writeReg(RFM95_REG_07_FRF_MID, (uint8_t)((freqReg >> 8) & 0xff)); - (void)RFM95_writeReg(RFM95_REG_08_FRF_LSB, (uint8_t)(freqReg & 0xff)); -} - -LOCAL bool RFM95_setTxPowerLevel(rfm95_powerLevel_t newPowerLevel) -{ - // RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST - newPowerLevel = max((int8_t)RFM95_MIN_POWER_LEVEL_DBM, newPowerLevel); - newPowerLevel = min((int8_t)RFM95_MAX_POWER_LEVEL_DBM, newPowerLevel); - if (newPowerLevel != RFM95.powerLevel) { - RFM95.powerLevel = newPowerLevel; - uint8_t val; - if (newPowerLevel > 20) { - // enable DAC, adds 3dBm - // The documentation is pretty confusing on this topic: PaSelect says the max power is 20dBm, - // but OutputPower claims it would be 17dBm. Measurements show 20dBm is correct - (void)RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_ENABLE); - val = newPowerLevel - 8; - } else { - (void)RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_DISABLE); - val = newPowerLevel - 5; - } - (void)RFM95_writeReg(RFM95_REG_09_PA_CONFIG, RFM95_PA_SELECT | val); - RFM95_DEBUG(PSTR("RFM95:PTX:LEVEL=%" PRIi8 "\n"), newPowerLevel); - return true; - } - return false; - -} - -LOCAL void RFM95_enableTCXO(void) -{ - while ((RFM95_readReg(RFM95_REG_4B_TCXO) & RFM95_TCXO_TCXO_INPUT_ON) != RFM95_TCXO_TCXO_INPUT_ON) { - (void)RFM95_writeReg(RFM95_REG_4B_TCXO, - (RFM95_readReg(RFM95_REG_4B_TCXO) | RFM95_TCXO_TCXO_INPUT_ON)); - } -} - -// Sets registers from a canned modem configuration structure -LOCAL void RFM95_setModemRegisters(const rfm95_modemConfig_t *config) -{ - (void)RFM95_writeReg(RFM95_REG_1D_MODEM_CONFIG1, config->reg_1d); - (void)RFM95_writeReg(RFM95_REG_1E_MODEM_CONFIG2, config->reg_1e); - (void)RFM95_writeReg(RFM95_REG_26_MODEM_CONFIG3, config->reg_26); -} - -LOCAL void RFM95_setPreambleLength(const uint16_t preambleLength) -{ - (void)RFM95_writeReg(RFM95_REG_20_PREAMBLE_MSB, (uint8_t)((preambleLength >> 8) & 0xff)); - (void)RFM95_writeReg(RFM95_REG_21_PREAMBLE_LSB, (uint8_t)(preambleLength & 0xff)); -} - -LOCAL void RFM95_setAddress(const uint8_t addr) -{ - RFM95.address = addr; -} - -LOCAL uint8_t RFM95_getAddress(void) -{ - return RFM95.address; -} - -LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode) -{ - if (RFM95.radioMode == newRadioMode) { - return false; - } - uint8_t regMode; - - if (newRadioMode == RFM95_RADIO_MODE_STDBY) { - regMode = RFM95_MODE_STDBY; - } else if (newRadioMode == RFM95_RADIO_MODE_SLEEP) { - regMode = RFM95_MODE_SLEEP; - } else if (newRadioMode == RFM95_RADIO_MODE_CAD) { - regMode = RFM95_MODE_CAD; - (void)RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x80); // Interrupt on CadDone, DIO0 - } else if (newRadioMode == RFM95_RADIO_MODE_RX) { - RFM95.dataReceived = false; - RFM95.ackReceived = false; - regMode = RFM95_MODE_RXCONTINUOUS; - (void)RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone, DIO0 - (void)RFM95_writeReg(RFM95_REG_0D_FIFO_ADDR_PTR, - RFM95_RX_FIFO_ADDR); // set FIFO ptr to beginning of RX FIFO address - } else if (newRadioMode == RFM95_RADIO_MODE_TX) { - regMode = RFM95_MODE_TX; - (void)RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x40); // Interrupt on TxDone, DIO0 - } else { - return false; - } - (void)RFM95_writeReg(RFM95_REG_01_OP_MODE, regMode); - - RFM95.radioMode = newRadioMode; - return true; -} - -LOCAL void RFM95_powerUp(void) -{ -#if defined(MY_RFM95_POWER_PIN) - RFM95_DEBUG(PSTR("RFM95:PWU\n")); // power up radio - hwDigitalWrite(MY_RFM95_POWER_PIN, HIGH); - delay(RFM95_POWERUP_DELAY_MS); -#endif -} -LOCAL void RFM95_powerDown(void) -{ -#if defined(MY_RFM95_POWER_PIN) - RFM95_DEBUG(PSTR("RFM95:PWD\n")); // power down radio - hwDigitalWrite(MY_RFM95_POWER_PIN, LOW); -#endif -} - -LOCAL bool RFM95_sleep(void) -{ - RFM95_DEBUG(PSTR("RFM95:RSL\n")); // put radio to sleep - return RFM95_setRadioMode(RFM95_RADIO_MODE_SLEEP); -} - -LOCAL bool RFM95_standBy(void) -{ - RFM95_DEBUG(PSTR("RFM95:RSB\n")); // put radio to standby - return RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); -} - - -// should be called immediately after reception in case sender wants ACK -LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, - const rfm95_RSSI_t RSSI, const rfm95_SNR_t SNR) -{ - RFM95_DEBUG(PSTR("RFM95:SAC:SEND ACK,TO=%" PRIu8 ",SEQ=%" PRIu16 ",RSSI=%" PRIi16 ",SNR=%" PRIi8 - "\n"),recipient,sequenceNumber, - RFM95_internalToRSSI(RSSI),RFM95_internalToSNR(SNR)); - rfm95_ack_t ACK; - ACK.sequenceNumber = sequenceNumber; - ACK.RSSI = RSSI; - ACK.SNR = SNR; - rfm95_controlFlags_t flags = 0u; - RFM95_setACKReceived(flags, true); - RFM95_setACKRSSIReport(flags, true); - (void)RFM95_send(recipient, (uint8_t *)&ACK, sizeof(rfm95_ack_t), flags); -} - -LOCAL bool RFM95_executeATC(const rfm95_RSSI_t currentRSSI, const rfm95_RSSI_t targetRSSI) -{ - rfm95_powerLevel_t newPowerLevel = RFM95.powerLevel; - const int16_t ownRSSI = RFM95_internalToRSSI(currentRSSI); - const int16_t uRange = RFM95_internalToRSSI(targetRSSI) + RFM95_ATC_TARGET_RANGE_DBM; - const int16_t lRange = RFM95_internalToRSSI(targetRSSI) - RFM95_ATC_TARGET_RANGE_DBM; - if (ownRSSI < lRange && RFM95.powerLevel < RFM95_MAX_POWER_LEVEL_DBM) { - // increase transmitter power - newPowerLevel++; - } else if (ownRSSI > uRange && RFM95.powerLevel > RFM95_MIN_POWER_LEVEL_DBM) { - // decrease transmitter power - newPowerLevel--; - } else { - // nothing to adjust - return false; - } - RFM95_DEBUG(PSTR("RFM95:ATC:ADJ TXL,cR=%" PRIi16 ",tR=%" PRIi16 "..%" PRIi16 ",TXL=%" PRIi8 "\n"), - ownRSSI, lRange, uRange, RFM95.powerLevel); - return RFM95_setTxPowerLevel(newPowerLevel); -} - -LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void *buffer, - const uint8_t bufferSize, const bool noACK) -{ - for (uint8_t retry = 0; retry < RFM95_RETRIES; retry++) { - RFM95_DEBUG(PSTR("RFM95:SWR:SEND,TO=%" PRIu8 ",SEQ=%" PRIu16 ",RETRY=%" PRIu8 "\n"), recipient, - RFM95.txSequenceNumber, - retry); - rfm95_controlFlags_t flags = 0u; - RFM95_setACKRequested(flags, !noACK); - // send packet - if (!RFM95_send(recipient, (uint8_t *)buffer, bufferSize, flags, !retry)) { - return false; - } - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_RX); - if (noACK) { - return true; - } - const uint32_t enterMS = hwMillis(); - while (hwMillis() - enterMS < RFM95_RETRY_TIMEOUT_MS && !RFM95.dataReceived) { - RFM95_handler(); - if (RFM95.ackReceived) { - const uint8_t sender = RFM95.currentPacket.header.sender; - const rfm95_sequenceNumber_t ACKsequenceNumber = RFM95.currentPacket.ACK.sequenceNumber; - const rfm95_controlFlags_t flag = RFM95.currentPacket.header.controlFlags; - const rfm95_RSSI_t RSSI = RFM95.currentPacket.ACK.RSSI; - //const rfm95_SNR_t SNR = RFM95.currentPacket.ACK.SNR; - RFM95.ackReceived = false; - // packet read, back to RX - RFM95_setRadioMode(RFM95_RADIO_MODE_RX); - if (sender == recipient && - (ACKsequenceNumber == RFM95.txSequenceNumber)) { - RFM95_DEBUG(PSTR("RFM95:SWR:ACK FROM=%" PRIu8 ",SEQ=%" PRIu16 ",RSSI=%" PRIi16 "\n"),sender, - ACKsequenceNumber, - RFM95_internalToRSSI(RSSI)); - //RFM95_clearRxBuffer(); - // ATC - if (RFM95.ATCenabled && RFM95_getACKRSSIReport(flag)) { - (void)RFM95_executeATC(RSSI, RFM95.ATCtargetRSSI); - } - return true; - } // seq check - } - doYield(); - } - RFM95_DEBUG(PSTR("!RFM95:SWR:NACK\n")); - const uint32_t enterCSMAMS = hwMillis(); - const uint16_t randDelayCSMA = enterMS % 100; - while (hwMillis() - enterCSMAMS < randDelayCSMA) { - doYield(); - } - } - if (RFM95.ATCenabled) { - // No ACK received, maybe out of reach: increase power level - (void)RFM95_setTxPowerLevel(RFM95.powerLevel + 1); - } - return false; -} - -// Wait until no channel activity detected or timeout -LOCAL bool RFM95_waitCAD(void) -{ - // receiver needs to be in STDBY before entering CAD mode - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); - (void)RFM95_setRadioMode(RFM95_RADIO_MODE_CAD); - const uint32_t enterMS = hwMillis(); - while (RFM95.radioMode == RFM95_RADIO_MODE_CAD && (hwMillis() - enterMS < RFM95_CAD_TIMEOUT_MS) ) { - doYield(); - RFM95_handler(); - } - return !RFM95.channelActive; -} - -LOCAL void RFM95_ATCmode(const bool OnOff, const int16_t targetRSSI) -{ - RFM95.ATCenabled = OnOff; - RFM95.ATCtargetRSSI = RFM95_RSSItoInternal(targetRSSI); -} - -LOCAL bool RFM95_sanityCheck(void) -{ - bool result = true; - result &= RFM95_readReg(RFM95_REG_0F_FIFO_RX_BASE_ADDR) == RFM95_RX_FIFO_ADDR; - result &= RFM95_readReg(RFM95_REG_0E_FIFO_TX_BASE_ADDR) == RFM95_TX_FIFO_ADDR; - result &= RFM95_readReg(RFM95_REG_23_MAX_PAYLOAD_LENGTH) == RFM95_MAX_PACKET_LEN; - return result; -} - - -LOCAL int16_t RFM95_getSendingRSSI(void) -{ - // own RSSI, as measured by the recipient - ACK part - if (RFM95_getACKRSSIReport(RFM95.currentPacket.header.controlFlags)) { - return RFM95_internalToRSSI(RFM95.currentPacket.ACK.RSSI); - } else { - // not possible - return INVALID_RSSI; - } -} - -LOCAL int16_t RFM95_getSendingSNR(void) -{ - // own SNR, as measured by the recipient - ACK part - if (RFM95_getACKRSSIReport(RFM95.currentPacket.header.controlFlags)) { - return static_cast(RFM95_internalToSNR(RFM95.currentPacket.ACK.SNR)); - } else { - // not possible - return INVALID_SNR; - } -} - -LOCAL int16_t RFM95_getReceivingRSSI(void) -{ - // RSSI from last received packet - return static_cast(RFM95_internalToRSSI(RFM95.currentPacket.RSSI)); -} - -LOCAL int16_t RFM95_getReceivingSNR(void) -{ - // SNR from last received packet - return static_cast(RFM95_internalToSNR(RFM95.currentPacket.SNR)); -} - -LOCAL uint8_t RFM95_getTxPowerLevel(void) -{ - return RFM95.powerLevel; -} - -LOCAL uint8_t RFM95_getTxPowerPercent(void) -{ - // report TX level in % - const uint8_t result = static_cast(100.0f * (RFM95.powerLevel - - RFM95_MIN_POWER_LEVEL_DBM) / - (RFM95_MAX_POWER_LEVEL_DBM - - RFM95_MIN_POWER_LEVEL_DBM)); - return result; -} -LOCAL bool RFM95_setTxPowerPercent(const uint8_t newPowerPercent) -{ - const rfm95_powerLevel_t newPowerLevel = static_cast - (RFM95_MIN_POWER_LEVEL_DBM + (RFM95_MAX_POWER_LEVEL_DBM - - RFM95_MIN_POWER_LEVEL_DBM) * (newPowerPercent / 100.0f)); - RFM95_DEBUG(PSTR("RFM95:SPP:PCT=%" PRIu8 ",TX LEVEL=%" PRIi8 "\n"), newPowerPercent,newPowerLevel); - return RFM95_setTxPowerLevel(newPowerLevel); -} - diff --git a/lib/MySensors/hal/transport/RFM95/driver/RFM95.h b/lib/MySensors/hal/transport/RFM95/driver/RFM95.h deleted file mode 100644 index 994d72c8..00000000 --- a/lib/MySensors/hal/transport/RFM95/driver/RFM95.h +++ /dev/null @@ -1,487 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on Mike McCauley's RFM95 library, Copyright (C) 2014 Mike McCauley - * Radiohead http://www.airspayce.com/mikem/arduino/RadioHead/index.html - * - * RFM95 driver refactored and optimized for MySensors, Copyright (C) 2017-2018 Olivier Mauti - * - * Changelog: - * - ACK with sequenceNumber - * - ATC control - * - * Definitions for HopeRF LoRa radios: - * http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf - * - */ - -/** -* @file RFM95.h -* -* @defgroup RFM95grp RFM95 -* @ingroup internals -* @{ -* -* RFM95 driver-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE -* - [!] Exclamation mark is prepended in case of error -* -* |E| SYS | SUB | Message | Comment -* |-|-------|------|----------------------------------------|----------------------------------------------------------------------------------- -* | | RFM95 | INIT | | Initialise RFM95 radio -* | | RFM95 | INIT | PIN,CS=%%d,IQP=%%d,IQN=%%d[,RST=%%d] | Pin configuration: chip select (CS), IRQ pin (IQP), IRQ number (IQN), Reset (RST) -* |!| RFM95 | INIT | SANCHK FAIL | Sanity check failed, check wiring or replace module -* |!| RFM95 | IRH | CRC FAIL | Incoming packet has CRC error, skip -* | | RFM95 | RCV | SEND ACK | ACK request received, sending ACK back -* | | RFM95 | PTC | LEVEL=%%d | Set TX power level -* | | RFM95 | SAC | SEND ACK,TO=%%d,RSSI=%%d,SNR=%%d | Send ACK to node (TO), RSSI of received message (RSSI), SNR of message (SNR) -* | | RFM95 | ATC | ADJ TXL,cR=%%d,tR=%%d..%%d,TXL=%%d | Adjust TX level, current RSSI (cR), target RSSI range (tR), TX level (TXL) -* | | RFM95 | SWR | SEND,TO=%%d,RETRY=%%d | Send message to (TO), NACK retry counter (RETRY) -* | | RFM95 | SWR | ACK FROM=%%d,SEQ=%%d,RSSI=%%d,SNR=%%d | ACK received from node (FROM), seq ID (SEQ), (RSSI), (SNR) -* |!| RFM95 | SWR | NACK | No ACK received -* | | RFM95 | SPP | PCT=%%d,TX LEVEL=%%d | Set TX level percent (PCT), TX level (LEVEL) -* | | RFM95 | PWD | | Power down radio -* | | RFM95 | PWU | | Power up radio -* -* RFM95 modem configuration -* -* BW = Bandwidth in kHz -* CR = Error correction code -* SF = Spreading factor, chips / symbol -* -* | CONFIG | BW | CR | SF | Comment | air-time (15 bytes) -* |------------------|-------|-----|------|-----------------------|------------------------ -* | BW125CR45SF128 | 125 | 4/5 | 128 | Default, medium range | 50ms -* | BW500CR45SF128 | 500 | 4/5 | 128 | Fast, short range | 15ms -* | BW31_25CR48SF512 | 31.25 | 4/8 | 512 | Slow, long range | 900ms -* | BW125CR48SF4096 | 125 | 4/8 | 4096 | Slow, long range | 1500ms -* -* See here for air-time calculation: https://docs.google.com/spreadsheets/d/1voGAtQAjC1qBmaVuP1ApNKs1ekgUjavHuVQIXyYSvNc -* -* @brief API declaration for RFM95 -* -*/ - -#ifndef _RFM95_h -#define _RFM95_h - -#include "RFM95registers.h" - -#if !defined(RFM95_SPI) -#define RFM95_SPI hwSPI //!< default SPI -#endif - -// default PIN assignments, can be overridden -#if defined(ARDUINO_ARCH_AVR) -#if defined(__AVR_ATmega32U4__) -#define DEFAULT_RFM95_IRQ_PIN (3) //!< DEFAULT_RFM95_IRQ_PIN -#else -#define DEFAULT_RFM95_IRQ_PIN (2) //!< DEFAULT_RFM95_IRQ_PIN -#endif -#elif defined(ARDUINO_ARCH_ESP8266) -#define DEFAULT_RFM95_IRQ_PIN (5) //!< DEFAULT_RFM95_IRQ_PIN -#elif defined(ARDUINO_ARCH_ESP32) -#define DEFAULT_RFM95_IRQ_PIN (16) //!< DEFAULT_RFM95_IRQ_PIN -#define DEFAULT_RFM95_IRQ_NUM digitalPinToInterrupt(DEFAULT_RFM95_IRQ_PIN) //!< DEFAULT_RFM95_IRQ_NUM -#elif defined(ARDUINO_ARCH_SAMD) -#define DEFAULT_RFM95_IRQ_PIN (2) //!< DEFAULT_RFM95_IRQ_PIN -#elif defined(LINUX_ARCH_RASPBERRYPI) -#define DEFAULT_RFM95_IRQ_PIN (22) //!< DEFAULT_RFM95_IRQ_PIN -#elif defined(ARDUINO_ARCH_STM32F1) -#define DEFAULT_RFM95_IRQ_PIN (PA3) //!< DEFAULT_RFM95_IRQ_PIN -#elif defined(TEENSYDUINO) -#define DEFAULT_RFM95_IRQ_PIN (8) //!< DEFAULT_RFM95_IRQ_PIN -#else -#define DEFAULT_RFM95_IRQ_PIN (2) //!< DEFAULT_RFM95_IRQ_PIN -#endif - -#define DEFAULT_RFM95_CS_PIN (SS) //!< DEFAULT_RFM95_CS_PIN - -// SPI settings -#define RFM95_SPI_DATA_ORDER MSBFIRST //!< SPI data order -#define RFM95_SPI_DATA_MODE SPI_MODE0 //!< SPI mode - -// RFM95 radio configurations: reg_1d, reg_1e, reg_26 (see datasheet) -#define RFM95_BW125CR45SF128 RFM95_BW_125KHZ | RFM95_CODING_RATE_4_5, RFM95_SPREADING_FACTOR_128CPS | RFM95_RX_PAYLOAD_CRC_ON, RFM95_AGC_AUTO_ON //!< 0x72,0x74,0x04 -#define RFM95_BW500CR45SF128 RFM95_BW_500KHZ | RFM95_CODING_RATE_4_5, RFM95_SPREADING_FACTOR_128CPS | RFM95_RX_PAYLOAD_CRC_ON, RFM95_AGC_AUTO_ON //!< 0x92,0x74,0x04 -#define RFM95_BW31_25CR48SF512 RFM95_BW_31_25KHZ | RFM95_CODING_RATE_4_8, RFM95_SPREADING_FACTOR_512CPS | RFM95_RX_PAYLOAD_CRC_ON, RFM95_AGC_AUTO_ON //!< 0x48,0x94,0x04 -#define RFM95_BW125CR48SF4096 RFM95_BW_125KHZ | RFM95_CODING_RATE_4_8, RFM95_SPREADING_FACTOR_4096CPS | RFM95_RX_PAYLOAD_CRC_ON, RFM95_AGC_AUTO_ON | RFM95_LOW_DATA_RATE_OPTIMIZE //!< 0x78,0xc4,0x0C - -#if !defined(RFM95_RETRY_TIMEOUT_MS) -// air-time approximation for timeout, 1 hop ~15 bytes payload - adjust if needed -// BW125/SF128: 50ms -// BW500/SF128: 15ms -// BW31.25/SF512: 900ms -// BW125/SF4096: 1500ms -#define RFM95_RETRY_TIMEOUT_MS (500ul) //!< Timeout for ACK, adjustments needed if modem configuration changed (air time different) -#endif - -#if !defined(MY_RFM95_TX_TIMEOUT_MS) -#define MY_RFM95_TX_TIMEOUT_MS (5*1000ul) //!< TX timeout -#endif - -// Frequency definitions -#define RFM95_169MHZ (169000000ul) //!< 169 Mhz -#define RFM95_315MHZ (315000000ul) //!< 315 Mhz -#define RFM95_434MHZ (433920000ul) //!< 433.92 Mhz -#define RFM95_868MHZ (868100000ul) //!< 868.1 Mhz -#define RFM95_915MHZ (915000000ul) //!< 915 Mhz - -#define RFM95_RETRIES (5u) //!< Retries in case of failed transmission -#define RFM95_FIFO_SIZE (0xFFu) //!< Max number of bytes the LORA Rx/Tx FIFO can hold -#define RFM95_RX_FIFO_ADDR (0x00u) //!< RX FIFO addr pointer -#define RFM95_TX_FIFO_ADDR (0x80u) //!< TX FIFO addr pointer -#define RFM95_MAX_PACKET_LEN (0x40u) //!< This is the maximum number of bytes that can be carried by the LORA -#define RFM95_PREAMBLE_LENGTH (8u) //!< Preamble length, default=8 -#define RFM95_CAD_TIMEOUT_MS (2*1000ul) //!< channel activity detection timeout -#define RFM95_POWERUP_DELAY_MS (100u) //!< Power up delay, allow VCC to settle, transport to become fully operational - -#define RFM95_PACKET_HEADER_VERSION (1u) //!< RFM95 packet header version -#define RFM95_MIN_PACKET_HEADER_VERSION (1u) //!< Minimal RFM95 packet header version -#define RFM95_BIT_ACK_REQUESTED (7u) //!< RFM95 header, controlFlag, bit 7 -#define RFM95_BIT_ACK_RECEIVED (6u) //!< RFM95 header, controlFlag, bit 6 -#define RFM95_BIT_ACK_RSSI_REPORT (5u) //!< RFM95 header, controlFlag, bit 5 - -#define RFM95_BROADCAST_ADDRESS (255u) //!< Broadcasting address -#define RFM95_ATC_TARGET_RANGE_DBM (2u) //!< ATC target range +/- dBm -#define RFM95_RSSI_OFFSET (137u) //!< RSSI offset -#define RFM95_TARGET_RSSI (-70) //!< RSSI target -#define RFM95_PROMISCUOUS (false) //!< RFM95 promiscuous mode - -#define RFM95_FXOSC (32*1000000ul) //!< The crystal oscillator frequency of the module -#define RFM95_FSTEP (RFM95_FXOSC / 524288.0f) //!< The Frequency Synthesizer step - -// helper macros -#define RFM95_getACKRequested(__value) ((bool)bitRead(__value, RFM95_BIT_ACK_REQUESTED)) //!< getACKRequested -#define RFM95_setACKRequested(__value, __flag) bitWrite(__value, RFM95_BIT_ACK_REQUESTED,__flag) //!< setACKRequested -#define RFM95_getACKReceived(__value) ((bool)bitRead(__value, RFM95_BIT_ACK_RECEIVED)) //!< getACKReceived -#define RFM95_setACKReceived(__value, __flag) bitWrite(__value, RFM95_BIT_ACK_RECEIVED,__flag) //!< setACKReceived -#define RFM95_setACKRSSIReport(__value, __flag) bitWrite(__value, RFM95_BIT_ACK_RSSI_REPORT,__flag) //!< setACKRSSIReport -#define RFM95_getACKRSSIReport(__value) ((bool)bitRead(__value, RFM95_BIT_ACK_RSSI_REPORT)) //!< getACKRSSIReport -#define RFM95_internalToSNR(__value) ((int8_t)(__value / 4)) //!< Convert internal SNR to SNR - -#define RFM95_MIN_POWER_LEVEL_DBM ((rfm95_powerLevel_t)5u) //!< min. power level -#if defined(MY_RFM95_MAX_POWER_LEVEL_DBM) -#define RFM95_MAX_POWER_LEVEL_DBM MY_RFM95_MAX_POWER_LEVEL_DBM //!< MY_RFM95_MAX_POWER_LEVEL_DBM -#else -#define RFM95_MAX_POWER_LEVEL_DBM ((rfm95_powerLevel_t)23u) //!< max. power level -#endif -/** -* @brief Radio modes -*/ -typedef enum { - RFM95_RADIO_MODE_RX = 0, //!< RX mode - RFM95_RADIO_MODE_TX = 1, //!< TX mode - RFM95_RADIO_MODE_CAD = 2, //!< CAD mode - RFM95_RADIO_MODE_SLEEP = 3, //!< SLEEP mode - RFM95_RADIO_MODE_STDBY = 4 //!< STDBY mode -} rfm95_radioMode_t; - -/** -* @brief RFM95 modem config registers -*/ -typedef struct { - uint8_t reg_1d; //!< Value for register REG_1D_MODEM_CONFIG1 - uint8_t reg_1e; //!< Value for register REG_1E_MODEM_CONFIG2 - uint8_t reg_26; //!< Value for register REG_26_MODEM_CONFIG3 -} rfm95_modemConfig_t; - -/** -* @brief Sequence number data type -*/ -typedef uint16_t rfm95_sequenceNumber_t; // will eventually change to uint8_t in 3.0 -/** -* @brief RSSI data type -*/ -typedef uint8_t rfm95_RSSI_t; -/** -* @brief SNR data type -*/ -typedef int8_t rfm95_SNR_t; -/** -* @brief Control flag data type -*/ -typedef uint8_t rfm95_controlFlags_t; -/** -* @brief Power level in dBm -*/ -typedef int8_t rfm95_powerLevel_t; -/** -* @brief RFM95 LoRa header -*/ -typedef struct { - uint8_t version; //!< Header version - uint8_t recipient; //!< Payload recipient - uint8_t sender; //!< Payload sender - rfm95_controlFlags_t controlFlags; //!< Control flags, used for ACK - rfm95_sequenceNumber_t sequenceNumber; //!< Packet sequence number, used for ACK -} __attribute__((packed)) rfm95_header_t; - -/** -* @brief RFM95 LoRa ACK packet structure -*/ -typedef struct { - rfm95_sequenceNumber_t sequenceNumber; //!< sequence number - rfm95_RSSI_t RSSI; //!< RSSI - rfm95_SNR_t SNR; //!< SNR -} __attribute__((packed)) rfm95_ack_t; - - -#define RFM95_HEADER_LEN sizeof(rfm95_header_t) //!< Size header inside LoRa payload -#define RFM95_MAX_PAYLOAD_LEN (RFM95_MAX_PACKET_LEN - RFM95_HEADER_LEN) //!< Max payload length - -/** -* @brief LoRa packet structure -*/ -typedef struct { - union { - struct { - rfm95_header_t header; //!< LoRa header - union { - uint8_t payload[RFM95_MAX_PAYLOAD_LEN]; //!< Payload, i.e. MySensors message - rfm95_ack_t ACK; //!< Union: ACK - }; - }; - uint8_t data[RFM95_MAX_PACKET_LEN]; //!< RAW - }; - uint8_t payloadLen; //!< Length of payload (excluding header) - rfm95_RSSI_t RSSI; //!< RSSI of current packet, RSSI = value - 137 - rfm95_SNR_t SNR; //!< SNR of current packet -} __attribute__((packed)) rfm95_packet_t; - - -/** -* @brief RFM95 internal variables -*/ -typedef struct { - uint8_t address; //!< Node address - rfm95_packet_t currentPacket; //!< Buffer for current packet - rfm95_sequenceNumber_t txSequenceNumber; //!< RFM95_txSequenceNumber - rfm95_powerLevel_t powerLevel; //!< TX power level dBm - rfm95_RSSI_t ATCtargetRSSI; //!< ATC: target RSSI - // 8 bit - rfm95_radioMode_t radioMode : 3; //!< current transceiver state - bool channelActive : 1; //!< RFM95_cad - bool ATCenabled : 1; //!< ATC enabled - bool ackReceived : 1; //!< ACK received - bool dataReceived : 1; //!< Data received - bool reserved : 1; //!< unused -} rfm95_internal_t; - -#define LOCAL static //!< static - -/** -* @brief Initialise the driver transport hardware and software -* @param frequencyHz Transmitter frequency in Hz -* @return True if initialisation succeeded -*/ -LOCAL bool RFM95_initialise(const uint32_t frequencyHz); -/** -* @brief Set the driver/node address -* @param addr -*/ -LOCAL void RFM95_setAddress(const uint8_t addr); -/** -* @brief Get driver/node address -* @return Node address -*/ -LOCAL uint8_t RFM95_getAddress(void); -/** -* @brief Sets all the registers required to configure the data modem in the RF95/96/97/98, including the -* bandwidth, spreading factor etc. -* @param config See modemConfig_t and references therein -*/ -LOCAL void RFM95_setModemRegisters(const rfm95_modemConfig_t *config); -/** -* @brief Tests whether a new message is available -* @return True if a new, complete, error-free uncollected message is available to be retreived by @ref RFM95_receive() -*/ -LOCAL bool RFM95_available(void); -/** -* @brief If a valid message is received, copy it to buf and return length. 0 byte messages are permitted. -* @param buf Location to copy the received message -* @param maxBufSize Max buffer size -* @return Number of bytes -*/ -LOCAL uint8_t RFM95_receive(uint8_t *buf, const uint8_t maxBufSize); -/** -* @brief RFM95_send -* @param recipient -* @param data -* @param len -* @param flags -* @param increaseSequenceCounter -* @return True if packet sent -*/ -LOCAL bool RFM95_send(const uint8_t recipient, uint8_t *data, const uint8_t len, - const rfm95_controlFlags_t flags, const bool increaseSequenceCounter = true); -/** -* @brief RFM95_sendFrame -* @param packet -* @param increaseSequenceCounter -* @return True if frame sent -*/ -LOCAL bool RFM95_sendFrame(rfm95_packet_t *packet, const bool increaseSequenceCounter = true); -/** -* @brief RFM95_setPreambleLength -* @param preambleLength -*/ -LOCAL void RFM95_setPreambleLength(const uint16_t preambleLength); -/** -* @brief Sets the transmitter and receiver centre frequency -* @param frequencyHz Frequency in Hz -*/ -LOCAL void RFM95_setFrequency(const uint32_t frequencyHz); -/** -* @brief Sets the transmitter power output level, and configures the transmitter pin -* @param newPowerLevel Transmitter power level in dBm (+5 to +23) -* @return True power level adjusted -*/ -LOCAL bool RFM95_setTxPowerLevel(rfm95_powerLevel_t newPowerLevel); - -/** -* @brief Sets the transmitter power output percent. -* @param newPowerPercent Transmitter power level in percent -* @return True power level adjusted -*/ -LOCAL bool RFM95_setTxPowerPercent(const uint8_t newPowerPercent); - -/** -* @brief Enable TCXO mode -* Call this immediately after init(), to force your radio to use an external -* frequency source, such as a Temperature Compensated Crystal Oscillator (TCXO). -* See the comments in the main documentation about the sensitivity of this radio to -* clock frequency especially when using narrow bandwidths. -* @note Has to be called while radio is in sleep mode. -*/ -LOCAL void RFM95_enableTCXO(void); - -/** -* @brief Sets the radio into low-power sleep mode -* @return true if sleep mode was successfully entered -*/ -LOCAL bool RFM95_sleep(void); -/** -* @brief Sets the radio into standby mode -* @return true if standby mode was successfully entered -*/ -LOCAL bool RFM95_standBy(void); -/** -* @brief Powerdown radio, if RFM95_POWER_PIN defined -*/ -LOCAL void RFM95_powerDown(void); -/** -* @brief Powerup radio, if RFM95_POWER_PIN defined -*/ -LOCAL void RFM95_powerUp(void); -/** -* @brief RFM95_sendACK -* @param recipient -* @param sequenceNumber -* @param RSSI (rfm95_RSSI_t) -* @param SNR (rfm95_SNR_t) -*/ -LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, - const rfm95_RSSI_t RSSI, const rfm95_SNR_t SNR); -/** -* @brief RFM95_sendWithRetry -* @param recipient -* @param buffer -* @param bufferSize -* @param noACK -* @return True if packet successfully sent -*/ -LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void *buffer, - const uint8_t bufferSize, const bool noACK); -/** -* @brief Wait until no channel activity detected -* @return True if no channel activity detected, False if timeout occured -*/ -LOCAL bool RFM95_waitCAD(void); - -/** -* @brief RFM95_setRadioMode -* @param newRadioMode -* @return True if mode changed -*/ -LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode); -/** -* @brief Low level interrupt handler -*/ -LOCAL void RFM95_interruptHandler(void); - -/** -* @brief Packet engine -*/ -LOCAL void RFM95_interruptHandling(void); - -/** -* @brief RFM95_handler -*/ -LOCAL void RFM95_handler(void); -/** -* @brief RFM95_getSendingRSSI -* @return RSSI Signal strength of last packet received -*/ -LOCAL int16_t RFM95_getReceivingRSSI(void); -/** -* @brief RFM95_getSendingRSSI -* @return RSSI Signal strength of last packet sent (if ACK and ATC enabled) -*/ -LOCAL int16_t RFM95_getSendingRSSI(void); -/** -* @brief RFM95_getReceivingSNR -* @return SNR -*/ -LOCAL int16_t RFM95_getReceivingSNR(void); -/** -* @brief RFM95_getSendingSNR -* @return SNR of last packet sent (if ACK and ATC enabled) -*/ -LOCAL int16_t RFM95_getSendingSNR(void); -/** -* @brief Get transmitter power level -* @return Transmitter power level in percents -*/ -LOCAL uint8_t RFM95_getTxPowerPercent(void); -/** -* @brief Get transmitter power level -* @return Transmitter power level in dBm -*/ -LOCAL uint8_t RFM95_getTxPowerLevel(void); -/** -* @brief RFM_executeATC -* @param currentRSSI -* @param targetRSSI -* @return True if power level adjusted -*/ -LOCAL bool RFM95_executeATC(const rfm95_RSSI_t currentRSSI, const rfm95_RSSI_t targetRSSI); -/** -* @brief RFM95_ATCmode -* @param targetRSSI Target RSSI for transmitter (default -60) -* @param OnOff True to enable ATC -*/ -LOCAL void RFM95_ATCmode(const bool OnOff, const int16_t targetRSSI = RFM95_TARGET_RSSI); -/** -* @brief RFM95_sanityCheck -* @return True if sanity check passed -*/ -LOCAL bool RFM95_sanityCheck(void); - -#endif - -/** @}*/ diff --git a/lib/MySensors/hal/transport/RFM95/driver/RFM95registers.h b/lib/MySensors/hal/transport/RFM95/driver/RFM95registers.h deleted file mode 100644 index 46d0366e..00000000 --- a/lib/MySensors/hal/transport/RFM95/driver/RFM95registers.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Based on Mike McCauley's RFM95 library, Copyright (C) 2014 Mike McCauley - * Radiohead http://www.airspayce.com/mikem/arduino/RadioHead/index.html - * - * RFM95 driver refactored and optimized for MySensors, Copyright (C) 2017-2018 Olivier Mauti - * - * Definitions for HopeRF LoRa radios: - * http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf - * - */ - -// Register access -#define RFM95_READ_REGISTER (0x7Fu) //!< reading register -#define RFM95_WRITE_REGISTER (0x80u) //!< writing register -#define RFM95_NOP (0x00u) //!< NOP - -// Registers, available in LoRa mode -#define RFM95_REG_00_FIFO 0x00 //!< REG_00_FIFO -#define RFM95_REG_01_OP_MODE 0x01 //!< REG_01_OP_MODE -#define RFM95_REG_02_RESERVED 0x02 //!< REG_02_RESERVED -#define RFM95_REG_03_RESERVED 0x03 //!< REG_03_RESERVED -#define RFM95_REG_04_RESERVED 0x04 //!< REG_04_RESERVED -#define RFM95_REG_05_RESERVED 0x05 //!< REG_05_RESERVED -#define RFM95_REG_06_FRF_MSB 0x06 //!< REG_06_FRF_MSB -#define RFM95_REG_07_FRF_MID 0x07 //!< REG_07_FRF_MID -#define RFM95_REG_08_FRF_LSB 0x08 //!< REG_08_FRF_LSB -#define RFM95_REG_09_PA_CONFIG 0x09 //!< REG_09_PA_CONFIG -#define RFM95_REG_0A_PA_RAMP 0x0a //!< REG_0A_PA_RAMP -#define RFM95_REG_0B_OCP 0x0b //!< REG_0B_OCP -#define RFM95_REG_0C_LNA 0x0c //!< REG_0C_LNA -#define RFM95_REG_0D_FIFO_ADDR_PTR 0x0d //!< REG_0D_FIFO_ADDR_PTR -#define RFM95_REG_0E_FIFO_TX_BASE_ADDR 0x0e //!< REG_0E_FIFO_TX_BASE_ADDR -#define RFM95_REG_0F_FIFO_RX_BASE_ADDR 0x0f //!< REG_0F_FIFO_RX_BASE_ADDR -#define RFM95_REG_10_FIFO_RX_CURRENT_ADDR 0x10 //!< REG_10_FIFO_RX_CURRENT_ADDR -#define RFM95_REG_11_IRQ_FLAGS_MASK 0x11 //!< REG_11_IRQ_FLAGS_MASK -#define RFM95_REG_12_IRQ_FLAGS 0x12 //!< REG_12_IRQ_FLAGS -#define RFM95_REG_13_RX_NB_BYTES 0x13 //!< REG_13_RX_NB_BYTES -#define RFM95_REG_14_RX_HEADER_CNT_VALUE_MSB 0x14 //!< REG_14_RX_HEADER_CNT_VALUE_MSB -#define RFM95_REG_15_RX_HEADER_CNT_VALUE_LSB 0x15 //!< REG_15_RX_HEADER_CNT_VALUE_LSB -#define RFM95_REG_16_RX_PACKET_CNT_VALUE_MSB 0x16 //!< REG_16_RX_PACKET_CNT_VALUE_MSB -#define RFM95_REG_17_RX_PACKET_CNT_VALUE_LSB 0x17 //!< REG_17_RX_PACKET_CNT_VALUE_LSB -#define RFM95_REG_18_MODEM_STAT 0x18 //!< REG_18_MODEM_STAT -#define RFM95_REG_19_PKT_SNR_VALUE 0x19 //!< REG_19_PKT_SNR_VALUE -#define RFM95_REG_1A_PKT_RSSI_VALUE 0x1a //!< REG_1A_PKT_RSSI_VALUE -#define RFM95_REG_1B_RSSI_VALUE 0x1b //!< REG_1B_RSSI_VALUE -#define RFM95_REG_1C_HOP_CHANNEL 0x1c //!< REG_1C_HOP_CHANNEL -#define RFM95_REG_1D_MODEM_CONFIG1 0x1d //!< REG_1D_MODEM_CONFIG1 -#define RFM95_REG_1E_MODEM_CONFIG2 0x1e //!< REG_1E_MODEM_CONFIG2 -#define RFM95_REG_1F_SYMB_TIMEOUT_LSB 0x1f //!< REG_1F_SYMB_TIMEOUT_LSB -#define RFM95_REG_20_PREAMBLE_MSB 0x20 //!< REG_20_PREAMBLE_MSB -#define RFM95_REG_21_PREAMBLE_LSB 0x21 //!< REG_21_PREAMBLE_LSB -#define RFM95_REG_22_PAYLOAD_LENGTH 0x22 //!< REG_22_PAYLOAD_LENGTH -#define RFM95_REG_23_MAX_PAYLOAD_LENGTH 0x23 //!< REG_23_MAX_PAYLOAD_LENGTH -#define RFM95_REG_24_HOP_PERIOD 0x24 //!< REG_24_HOP_PERIOD -#define RFM95_REG_25_FIFO_RX_BYTE_ADDR 0x25 //!< REG_25_FIFO_RX_BYTE_ADDR -#define RFM95_REG_26_MODEM_CONFIG3 0x26 //!< REG_26_MODEM_CONFIG3 - -// Reserved when in LoRa mode -#define RFM95_REG_40_DIO_MAPPING1 0x40 //!< REG_40_DIO_MAPPING1 -#define RFM95_REG_41_DIO_MAPPING2 0x41 //!< REG_41_DIO_MAPPING2 -#define RFM95_REG_42_VERSION 0x42 //!< REG_42_VERSION -#define RFM95_REG_4B_TCXO 0x4b //!< REG_4B_TCXO -#define RFM95_REG_4D_PA_DAC 0x4d //!< REG_4D_PA_DAC -#define RFM95_REG_5B_FORMER_TEMP 0x5b //!< REG_5B_FORMER_TEMP -#define RFM95_REG_61_AGC_REF 0x61 //!< REG_61_AGC_REF -#define RFM95_REG_62_AGC_THRESH1 0x62 //!< REG_62_AGC_THRESH1 -#define RFM95_REG_63_AGC_THRESH2 0x63 //!< REG_63_AGC_THRESH2 -#define RFM95_REG_64_AGC_THRESH3 0x64 //!< REG_64_AGC_THRESH3 - -// RFM95_REG_01_OP_MODE 0x01 -#define RFM95_LONG_RANGE_MODE 0x80 //!< LONG_RANGE_MODE -#define RFM95_ACCESS_SHARED_REG 0x40 //!< ACCESS_SHARED_REG - -#define RFM95_MODE_SLEEP 0x00 //!< MODE_SLEEP -#define RFM95_MODE_STDBY 0x01 //!< MODE_STDBY -#define RFM95_MODE_FSTX 0x02 //!< MODE_FSTX -#define RFM95_MODE_TX 0x03 //!< MODE_TX -#define RFM95_MODE_FSRX 0x04 //!< MODE_FSRX -#define RFM95_MODE_RXCONTINUOUS 0x05 //!< MODE_RXCONTINUOUS -#define RFM95_MODE_RXSINGLE 0x06 //!< MODE_RXSINGLE -#define RFM95_MODE_CAD 0x07 //!< MODE_CAD - -// RFM95_REG_09_PA_CONFIG 0x09 -#define RFM95_OUTPUT_POWER 0x0F //!< OUTPUT_POWER -#define RFM95_MAX_POWER 0x70 //!< MAX_POWER -#define RFM95_PA_SELECT 0x80 //!< PA_SELECT - -// RFM95_REG_0A_PA_RAMP 0x0a -#define RFM95_PA_RAMP_3_4MS 0x00 //!< PA_RAMP_3_4MS -#define RFM95_PA_RAMP_2MS 0x01 //!< PA_RAMP_2MS -#define RFM95_PA_RAMP_1MS 0x02 //!< PA_RAMP_1MS -#define RFM95_PA_RAMP_500US 0x03 //!< PA_RAMP_500US -#define RFM95_PA_RAMP_250US 0x04 //!< PA_RAMP_250US -#define RFM95_PA_RAMP_125US 0x05 //!< PA_RAMP_125US -#define RFM95_PA_RAMP_100US 0x06 //!< PA_RAMP_100US -#define RFM95_PA_RAMP_62US 0x07 //!< PA_RAMP_62US -#define RFM95_PA_RAMP_50US 0x08 //!< PA_RAMP_50US -#define RFM95_PA_RAMP_40US 0x09 //!< PA_RAMP_40US -#define RFM95_PA_RAMP_31US 0x0A //!< PA_RAMP_31US -#define RFM95_PA_RAMP_25US 0x0B //!< PA_RAMP_25US -#define RFM95_PA_RAMP_20US 0x0C //!< PA_RAMP_20US -#define RFM95_PA_RAMP_15US 0x0D //!< PA_RAMP_15US -#define RFM95_PA_RAMP_12US 0x0E //!< PA_RAMP_12US -#define RFM95_PA_RAMP_10US 0x0F //!< PA_RAMP_10US -#define RFM95_LOW_PN_TX_PLL_OFF 0x10 //!< LOW_PN_TX_PLL_OFF - -// RFM95_REG_0B_OCP 0x0b -#define RFM95_OCP_TRIM 0x1f //!< OCP_TRIM -#define RFM95_OCP_ON 0x20 //!< OCP_ON - -// RFM95_REG_0C_LNA 0x0c -#define RFM95_LNA_BOOST_DEFAULT 0x20 //!< LNA_BOOST_DEFAULT -#define RFM95_LNA_BOOST 0x03 //!< LNA_BOOST - -// RFM95_REG_11_IRQ_FLAGS_MASK 0x11 -#define RFM95_CAD_DETECTED_MASK 0x01 //!< CAD_DETECTED_MASK -#define RFM95_FHSS_CHANGE_CHANNEL_MASK 0x02 //!< FHSS_CHANGE_CHANNEL_MASK -#define RFM95_CAD_DONE_MASK 0x04 //!< CAD_DONE_MASK -#define RFM95_TX_DONE_MASK 0x08 //!< TX_DONE_MASK -#define RFM95_VALID_HEADER_MASK 0x10 //!< VALID_HEADER_MASK -#define RFM95_PAYLOAD_CRC_ERROR_MASK 0x20 //!< PAYLOAD_CRC_ERROR_MASK -#define RFM95_RX_DONE_MASK 0x40 //!< RX_DONE_MASK -#define RFM95_RX_TIMEOUT_MASK 0x80 //!< RX_TIMEOUT_MASK - -// RFM95_REG_12_IRQ_FLAGS 0x12 -#define RFM95_CAD_DETECTED 0x01 //!< CAD_DETECTED -#define RFM95_FHSS_CHANGE_CHANNEL 0x02 //!< FHSS_CHANGE_CHANNEL -#define RFM95_CAD_DONE 0x04 //!< CAD_DONE -#define RFM95_TX_DONE 0x08 //!< TX_DONE -#define RFM95_VALID_HEADER 0x10 //!< VALID_HEADER -#define RFM95_PAYLOAD_CRC_ERROR 0x20 //!< PAYLOAD_CRC_ERROR -#define RFM95_RX_DONE 0x40 //!< RX_DONE -#define RFM95_RX_TIMEOUT 0x80 //!< RX_TIMEOUT -#define RFM95_CLEAR_IRQ 0xFF // - * Copyright (C) 2013-2019 Sensnology AB - * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * ------------------------------------------------------------------------------- - * - * Copyright (c) 2013, Majenko Technologies and S.J.Hoeksma - * Copyright (c) 2015, LeoDesigner - * https://github.com/leodesigner/mysensors-serial-transport - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those - * of the authors and should not be interpreted as representing official policies, - * either expressed or implied, of Majenko Technologies. - ********************************************************************************/ - -// transport(Serial,0,-1); // serial port, node, dePin (-1 disabled) - -// Serial Transport - -#ifdef __linux__ -#include "SerialPort.h" -#endif - -#if defined(MY_RS485_DE_PIN) -#if !defined(MY_RS485_DE_INVERSE) -#define assertDE() hwDigitalWrite(MY_RS485_DE_PIN, HIGH); delayMicroseconds(5) -#define deassertDE() hwDigitalWrite(MY_RS485_DE_PIN, LOW) -#else -#define assertDE() hwDigitalWrite(MY_RS485_DE_PIN, LOW); delayMicroseconds(5) -#define deassertDE() hwDigitalWrite(MY_RS485_DE_PIN, HIG) -#endif -#else -#define assertDE() -#define deassertDE() -#endif - -// We only use SYS_PACK in this application -#define ICSC_SYS_PACK 0x58 - -// Receiving header information -char _header[6]; - -// Reception state machine control and storage variables -unsigned char _recPhase; -unsigned char _recPos; -unsigned char _recCommand; -unsigned char _recLen; -unsigned char _recStation; -unsigned char _recSender; -unsigned char _recCS; -unsigned char _recCalcCS; - - -#if defined(__linux__) -SerialPort _dev = SerialPort(MY_RS485_HWSERIAL); -#elif defined(MY_RS485_HWSERIAL) -HardwareSerial& _dev = MY_RS485_HWSERIAL; -#else -AltSoftSerial _dev; -#endif - -unsigned char _nodeId; -char _data[MY_RS485_MAX_MESSAGE_LENGTH]; -uint8_t _packet_len; -unsigned char _packet_from; -bool _packet_received; - -// Packet wrapping characters, defined in standard ASCII table -#define SOH 1 -#define STX 2 -#define ETX 3 -#define EOT 4 - - - -//Reset the state machine and release the data pointer -void _serialReset() -{ - _recPhase = 0; - _recPos = 0; - _recLen = 0; - _recCommand = 0; - _recCS = 0; - _recCalcCS = 0; -} - -// This is the main reception state machine. Progress through the states -// is keyed on either special control characters, or counted number of bytes -// received. If all the data is in the right format, and the calculated -// checksum matches the received checksum, AND the destination station is -// our station ID, then look for a registered command that matches the -// command code. If all the above is true, execute the command's -// function. -bool _serialProcess() -{ - unsigned char i; - if (!_dev.available()) { - return false; - } - - while(_dev.available()) { - char inch; - inch = _dev.read(); - - switch(_recPhase) { - - // Case 0 looks for the header. Bytes arrive in the serial interface and get - // shifted through a header buffer. When the start and end characters in - // the buffer match the SOH/STX pair, and the destination station ID matches - // our ID, save the header information and progress to the next state. - case 0: - memcpy(&_header[0],&_header[1],5); - _header[5] = inch; - if ((_header[0] == SOH) && (_header[5] == STX) && (_header[1] != _header[2])) { - _recCalcCS = 0; - _recStation = _header[1]; - _recSender = _header[2]; - _recCommand = _header[3]; - _recLen = _header[4]; - - for (i=1; i<=4; i++) { - _recCalcCS += _header[i]; - } - _recPhase = 1; - _recPos = 0; - - //Avoid _data[] overflow - if (_recLen >= MY_RS485_MAX_MESSAGE_LENGTH) { - _serialReset(); - break; - } - - //Check if we should process this message - //We reject the message if we are the sender - //We reject if we are not the receiver and message is not a broadcast - if ((_recSender == _nodeId) || - (_recStation != _nodeId && - _recStation != BROADCAST_ADDRESS)) { - _serialReset(); - break; - } - - if (_recLen == 0) { - _recPhase = 2; - } - - } - break; - - // Case 1 receives the data portion of the packet. Read in "_recLen" number - // of bytes and store them in the _data array. - case 1: - _data[_recPos++] = inch; - _recCalcCS += inch; - if (_recPos == _recLen) { - _recPhase = 2; - } - break; - - // After the data comes a single ETX character. Do we have it? If not, - // reset the state machine to default and start looking for a new header. - case 2: - // Packet properly terminated? - if (inch == ETX) { - _recPhase = 3; - } else { - _serialReset(); - } - break; - - // Next comes the checksum. We have already calculated it from the incoming - // data, so just store the incoming checksum byte for later. - case 3: - _recCS = inch; - _recPhase = 4; - break; - - // The final state - check the last character is EOT and that the checksum matches. - // If that test passes, then look for a valid command callback to execute. - // Execute it if found. - case 4: - if (inch == EOT) { - if (_recCS == _recCalcCS) { - // First, check for system level commands. It is possible - // to register your own callback as well for system level - // commands which will be called after the system default - // hook. - - switch (_recCommand) { - case ICSC_SYS_PACK: - _packet_from = _recSender; - _packet_len = _recLen; - _packet_received = true; - break; - } - } - } - //Clear the data - _serialReset(); - //Return true, we have processed one command - return true; - break; - } - } - return true; -} - -bool transportSend(const uint8_t to, const void* data, const uint8_t len, const bool noACK) -{ - (void)noACK; // not implemented - const char *datap = static_cast(data); - unsigned char i; - unsigned char cs = 0; - - // This is how many times to try and transmit before failing. - unsigned char timeout = 10; - - // Let's start out by looking for a collision. If there has been anything seen in - // the last millisecond, then wait for a random time and check again. - - while (_serialProcess()) { - unsigned char del; - del = rand() % 20; - for (i = 0; i < del; i++) { - delay(1); - _serialProcess(); - } - timeout--; - if (timeout == 0) { - // Failed to transmit!!! - return false; - } - } - -#if defined(MY_RS485_DE_PIN) -#if !defined(MY_RS485_DE_INVERSE) - hwDigitalWrite(MY_RS485_DE_PIN, HIGH); -#else - hwDigitalWrite(MY_RS485_DE_PIN, LOW); -#endif - delayMicroseconds(5); -#endif - - // Start of header by writing multiple SOH - for(byte w=0; w= 100 -#if ARDUINO >= 104 - // Arduino 1.0.4 and upwards does it right - _dev.flush(); -#else - // Between 1.0.0 and 1.0.3 it almost does it - need to compensate - // for the hardware buffer. Delay for 2 bytes worth of transmission. - _dev.flush(); - delayMicroseconds((20000000UL/9600)+1); -#endif -#elif defined(__linux__) - _dev.flush(); -#endif -#endif -#if !defined(MY_RS485_DE_INVERSE) - hwDigitalWrite(MY_RS485_DE_PIN, LOW); -#else - hwDigitalWrite(MY_RS485_DE_PIN, HIGH); -#endif -#endif - return true; -} - - - -bool transportInit(void) -{ - // Reset the state machine - _dev.begin(MY_RS485_BAUD_RATE); - _serialReset(); -#if defined(MY_RS485_DE_PIN) - hwPinMode(MY_RS485_DE_PIN, OUTPUT); -#if !defined(MY_RS485_DE_INVERSE) - hwDigitalWrite(MY_RS485_DE_PIN, LOW); -#else - hwDigitalWrite(MY_RS485_DE_PIN, HIGH); -#endif -#endif - return true; -} - -void transportSetAddress(const uint8_t address) -{ - _nodeId = address; -} - -uint8_t transportGetAddress(void) -{ - return _nodeId; -} - - -bool transportDataAvailable(void) -{ - _serialProcess(); - return _packet_received; -} - -bool transportSanityCheck(void) -{ - // not implemented yet - return true; -} - -uint8_t transportReceive(void* data) -{ - if (_packet_received) { - memcpy(data,_data,_packet_len); - _packet_received = false; - return _packet_len; - } else { - return (0); - } -} - -void transportPowerDown(void) -{ - // Nothing to shut down here -} - -void transportPowerUp(void) -{ - // not implemented -} - -void transportSleep(void) -{ - // not implemented -} - -void transportStandBy(void) -{ - // not implemented -} - -int16_t transportGetSendingRSSI(void) -{ - // not implemented - return INVALID_RSSI; -} - -int16_t transportGetReceivingRSSI(void) -{ - // not implemented - return INVALID_RSSI; -} - -int16_t transportGetSendingSNR(void) -{ - // not implemented - return INVALID_SNR; -} - -int16_t transportGetReceivingSNR(void) -{ - // not implemented - return INVALID_SNR; -} - -int16_t transportGetTxPowerPercent(void) -{ - // not implemented - return static_cast(100); -} - -int16_t transportGetTxPowerLevel(void) -{ - // not implemented - return static_cast(100); -} - -bool transportSetTxPowerPercent(const uint8_t powerPercent) -{ - // not possible - (void)powerPercent; - return false; -} diff --git a/lib/MySensors/keywords.txt b/lib/MySensors/keywords.txt deleted file mode 100644 index f245dbb5..00000000 --- a/lib/MySensors/keywords.txt +++ /dev/null @@ -1,376 +0,0 @@ -####################################### -# Datatypes (KEYWORD1) -####################################### -MyMessage KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### -present KEYWORD2 -send KEYWORD2 -sendSketchInfo KEYWORD2 -sendBatteryLevel KEYWORD2 -sendHeartbeat KEYWORD2 -getNodeId KEYWORD2 -request KEYWORD2 -requestTime KEYWORD2 -saveState KEYWORD2 -loadState KEYWORD2 -wait KEYWORD2 -receive KEYWORD2 -receiveTime KEYWORD2 -loop KEYWORD2 -before KEYWORD2 -setup KEYWORD2 -presentation KEYWORD2 -sleep KEYWORD2 -smartSleep KEYWORD2 - -###################################### -# Constants (LITERAL1) -####################################### -# General -MY_BAUD_RATE LITERAL1 -MY_CORE_ONLY LITERAL1 -MY_CORE_MIN_VERSION LITERAL1 -MY_CORE_VERSION LITERAL1 -MY_CRITICAL_SECTION LITERAL1 -MY_DISABLE_RAM_ROUTING_TABLE_FEATURE LITERAL1 -MY_DISABLE_REMOTE_RESET LITERAL1 -MY_DISABLED_SERIAL LITERAL1 -MY_INDICATION_HANDLER LITERAL1 -MY_RX_MESSAGE_BUFFER_SIZE LITERAL1 -MY_RX_MESSAGE_BUFFER_FEATURE LITERAL1 -MY_SERIAL_OUTPUT_SIZE LITERAL1 -MY_SLEEP_NOT_POSSIBLE LITERAL1 -MY_SPLASH_SCREEN_DISABLED LITERAL1 -MY_WAKE_UP_BY_TIMER LITERAL1 - -# transport -AUTO LITERAL1 -MY_CORE_COMPATIBILITY_CHECK LITERAL1 -MY_DEBUG_VERBOSE_TRANSPORT LITERAL1 -MY_NODE_ID LITERAL1 -MY_PARENT_NODE_ID LITERAL1 -MY_PARENT_NODE_IS_STATIC LITERAL1 -MY_PASSIVE_NODE LITERAL1 -MY_RAM_ROUTING_TABLE_FEATURE LITERAL1 -MY_REGISTRATION_CONTROLLER LITERAL1 -MY_REGISTRATION_DEFAULT LITERAL1 -MY_REGISTRATION_FEATURE LITERAL1 -MY_REGISTRATION_RETRIES LITERAL1 -MY_REPEATER_FEATURE LITERAL1 -MY_ROUTING_TABLE_SAVE_INTERVAL_MS LITERAL1 -MY_SIGNAL_REPORT_ENABLED LITERAL1 -MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS LITERAL1 -MY_SMART_SLEEP_WAIT_DURATION_MS LITERAL1 -MY_TRANSPORT_CHKUPL_INTERVAL_MS LITERAL1 -MY_TRANSPORT_DISCOVERY_INTERVAL_MS LITERAL1 -MY_TRANSPORT_MAX_TSM_FAILURES LITERAL1 -MY_TRANSPORT_MAX_TX_FAILURES LITERAL1 -MY_TRANSPORT_SANITY_CHECK LITERAL1 -MY_TRANSPORT_SANITY_CHECK_INTERVAL LITERAL1 -MY_TRANSPORT_SANITY_CHECK_INTERVAL_MS LITERAL1 -MY_TRANSPORT_STATE_RETRIES LITERAL1 -MY_TRANSPORT_STATE_TIMEOUT_MS LITERAL1 -MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE_MS LITERAL1 -MY_TRANSPORT_TIMEOUT_FAILURE_STATE_MS LITERAL1 -MY_TRANSPORT_UPLINK_CHECK_DISABLED LITERAL1 -MY_TRANSPORT_WAIT_READY_MS LITERAL1 - -# debug -MY_DEBUG LITERAL1 -MY_DEBUGDEVICE LITERAL1 -MY_DEBUG_VERBOSE_GATEWAY LITERAL1 -MY_SPECIAL_DEBUG LITERAL1 - -# OTA -MY_DEBUG_OTA LITERAL1 -MY_DEBUG_OTA_DISABLE_ECHO LITERAL1 -MY_DEBUG_VERBOSE_OTA_UPDATE LITERAL1 -MY_DEFAULT_ERR_LED_PIN LITERAL1 -MY_DEFAULT_LED_BLINK_PERIOD LITERAL1 -MY_DEFAULT_RX_LED_PIN LITERAL1 -MY_DEFAULT_TX_LED_PIN LITERAL1 -MY_INCLUSION_MODE_FEATURE LITERAL1 -MY_INCLUSION_BUTTON_FEATURE LITERAL1 -MY_INCLUSION_MODE_BUTTON_PIN LITERAL1 -MY_INCLUSION_MODE_DURATION LITERAL1 -MY_INCLUSION_LED_PIN LITERAL1 -MY_OTA_FIRMWARE_FEATURE LITERAL1 -MY_OTA_FLASH_SS LITERAL1 -MY_OTA_FLASH_JDECID LITERAL1 -MY_OTA_LOG_RECEIVER_FEATURE LITERAL1 -MY_OTA_LOG_SENDER_FEATURE LITERAL1 -MY_OTA_USE_I2C_EEPROM LITERAL1 -MY_SPIFLASH_SST25TYPE LITERAL1 -MY_WITH_LEDS_BLINKING_INVERSE LITERAL1 -MY_OTA_RETRY LITERAL1 -MY_OTA_RETRY_DELAY LITERAL1 - -# Signing -MY_DEBUG_VERBOSE_SIGNING LITERAL1 -MY_ENCRYPTION_SIMPLE_PASSWD LITERAL1 -MY_NODE_LOCK_FEATURE LITERAL1 -MY_NODE_UNLOCK_PIN LITERAL1 -MY_NODE_LOCK_COUNTER_MAX LITERAL1 -MY_SECURITY_SIMPLE_PASSWD LITERAL1 -MY_SIGNING_ATSHA204 LITERAL1 -MY_SIGNING_ATSHA204_PIN LITERAL1 -MY_SIGNING_NODE_WHITELISTING LITERAL1 -MY_SIGNING_SIMPLE_PASSWD LITERAL1 -MY_SIGNING_SOFT LITERAL1 -MY_SIGNING_SOFT_RANDOMSEED_PIN LITERAL1 -MY_SIGNING_REQUEST_SIGNATURES LITERAL1 -MY_SIGNING_WEAK_SECURITY LITERAL1 -MY_VERIFICATION_TIMEOUT_MS LITERAL1 - -# Random -MY_HW_HAS_GETENTROPY LITERAL1 -hwGetentropy KEYWORD2 - -# TinyGSM -MY_GATEWAY_TINYGSM LITERAL1 -MY_GSM_APN LITERAL1 -MY_GSM_BAUDRATE LITERAL1 -MY_GSM_PIN LITERAL1 -MY_GSM_PSW LITERAL1 -MY_GSM_RX LITERAL1 -MY_GSM_SSID LITERAL1 -MY_GSM_TX LITERAL1 -MY_GSM_USR LITERAL1 - -# SoftSPI -MY_SOFTSPI LITERAL1 -MY_SOFT_SPI_MISO_PIN LITERAL1 -MY_SOFT_SPI_MOSI_PIN LITERAL1 -MY_SOFT_SPI_SCK_PIN LITERAL1 - -# TransportHAL -MY_DEBUG_VERBOSE_TRANSPORT_HAL LITERAL1 - -# RF24 -MY_DEBUG_VERBOSE_RF24 LITERAL1 -MY_RADIO_RF24 LITERAL1 -MY_RF24_ADDR_WIDTH LITERAL1 -MY_RF24_BASE_RADIO_ID LITERAL1 -MY_RF24_ENABLE_ENCRYPTION LITERAL1 -MY_RF24_CE_PIN LITERAL1 -MY_RF24_CHANNEL LITERAL1 -MY_RF24_CS_PIN LITERAL1 -MY_RF24_DATARATE LITERAL1 -MY_RF24_IRQ_PIN LITERAL1 -MY_RF24_PA_LEVEL LITERAL1 -MY_RF24_POWER_PIN LITERAL1 -MY_RF24_SPI_SPEED LITERAL1 - -# NRF5 -MY_DEBUG_VERBOSE_NRF5_ESB LITERAL1 -MY_NRF5_ESB_ADDR_WIDTH LITERAL1 -MY_NRF5_ESB_BASE_RADIO_ID LITERAL1 -MY_NRF5_ESB_CHANNEL LITERAL1 -MY_NRF5_ESB_ENABLE_ENCRYPTION LITERAL1 -MY_NRF5_ESB_MODE LITERAL1 -MY_NRF5_ESB_PA_LEVEL LITERAL1 -MY_NRF5_ESB_RX_BUFFER_SIZE LITERAL1 -MY_NRF5_ESB_REVERSE_ACK_RX LITERAL1 -MY_NRF5_ESB_REVERSE_ACK_TX LITERAL1 -MY_RADIO_NRF5_ESB LITERAL1 - -# RFM95 -MY_DEBUG_VERBOSE_RFM95 LITERAL1 -MY_RADIO_RFM95 LITERAL1 -MY_RFM95_ATC_MODE_DISABLED LITERAL1 -MY_RFM95_ATC_TARGET_RSSI LITERAL1 -MY_RFM95_ATC_TARGET_RSSI_DBM LITERAL1 -MY_RFM95_CS_PIN LITERAL1 -MY_RFM95_FREQUENCY LITERAL1 -MY_RFM95_IRQ_NUM LITERAL1 -MY_RFM95_IRQ_PIN LITERAL1 -MY_RFM95_MAX_POWER_LEVEL_DBM LITERAL1 -MY_RFM95_MODEM_CONFIGRUATION LITERAL1 -MY_RFM95_POWER_PIN LITERAL1 -MY_RFM95_RST_PIN LITERAL1 -MY_RFM95_SPI_SPEED LITERAL1 -MY_RFM95_TCXO LITERAL1 -MY_RFM95_TX_POWER LITERAL1 -MY_RFM95_TX_POWER_DBM LITERAL1 -MY_RFM95_TX_TIMEOUT_MS LITERAL1 -MY_RFM95_ENABLE_ENCRYPTION LITERAL1 - -# RFM69 -MY_DEBUG_VERBOSE_RFM69 LITERAL1 -MY_DEBUG_VERBOSE_RFM69_REGISTERS LITERAL1 -MY_IS_RFM69HW LITERAL1 -MY_RADIO_RFM69 LITERAL1 -MY_RFM69_ATC_MODE_DISABLED LITERAL1 -MY_RFM69_ATC_TARGET_RSSI_DBM LITERAL1 -MY_RFM69_BITRATE_LSB LITERAL1 -MY_RFM69_BITRATE_MSB LITERAL1 -MY_RFM69_CS_PIN LITERAL1 -MY_RFM69_CSMA_ADD_DELAY_BASE LITERAL1 -MY_RFM69_CSMA_ADD_DELAY_COUNT LITERAL1 -MY_RFM69_CSMA_LIMIT_DBM LITERAL1 -MY_RFM69_CSMA_TIMEOUT_MS LITERAL1 -MY_RFM69_DEFAULT_LISTEN_IDLE_US LITERAL1 -MY_RFM69_DEFAULT_LISTEN_RX_US LITERAL1 -MY_RFM69_ENABLE_ENCRYPTION LITERAL1 -MY_RFM69_ENABLE_LISTENMODE LITERAL1 -MY_RFM69_FREQUENCY LITERAL1 -MY_RFM69_IRQ_NUM LITERAL1 -MY_RFM69_IRQ_PIN LITERAL1 -MY_RFM69_MAX_POWER_LEVEL_DBM LITERAL1 -MY_RFM69_MODEM_CONFIGURATION LITERAL1 -MY_RFM69_NETWORKID LITERAL1 -MY_RFM69_NEW_DRIVER LITERAL1 -MY_RFM69_POWER_PIN LITERAL1 -MY_RFM69_RST_PIN LITERAL1 -MY_RFM69_SPI_SPEED LITERAL1 -MY_RFM69_TX_TIMEOUT_MS LITERAL1 -MY_RFM69_TX_POWER_DBM LITERAL1 - -# RS485 -MY_RS485 LITERAL1 -MY_RS485_BAUD_RATE LITERAL1 -MY_RS485_DE_PIN LITERAL1 -MY_RS485_DE_INVERSE LITERAL1 -MY_RS485_HWSERIAL LITERAL1 -MY_RS485_MAX_MESSAGE_LENGTH LITERAL1 -MY_RS485_SOH_COUNT LITERAL1 - -# Gateway / MQTT -MY_GATEWAY_CLIENT_MODE LITERAL1 -MY_GATEWAY_ENC28J60 LITERAL1 -MY_GATEWAY_ESP32 LITERAL1 -MY_GATEWAY_ESP8266 LITERAL1 -MY_GATEWAY_MQTT_CLIENT LITERAL1 -MY_GATEWAY_SERIAL LITERAL1 -MY_GATEWAY_W5100 LITERAL1 -MY_HOSTNAME LITERAL1 -MY_INCLUSION_BUTTON_EXTERNAL_PULLUP LITERAL1 -MY_MQTT_CLIENT_ID LITERAL1 -MY_MQTT_CLIENT_PUBLISH_RETAIN LITERAL1 -MY_MQTT_PASSWORD LITERAL1 -MY_MQTT_PUBLISH_TOPIC_PREFIX LITERAL1 -MY_MQTT_SUBSCRIBE_TOPIC_PREFIX LITERAL1 -MY_MQTT_USER LITERAL1 -MY_W5100_SPI_EN LITERAL1 -MY_WIFI_SSID LITERAL1 -MY_WIFI_BSSID LITERAL1 -MY_WIFI_PASSWORD LITERAL1 - -# Ethernet -MY_CONTROLLER_IP_ADDRESS LITERAL1 -MY_CONTROLLER_URL_ADDRESS LITERAL1 -MY_GATEWAY_MAX_CLIENTS LITERAL1 -MY_GATEWAY_MAX_RECEIVE_LENGTH LITERAL1 -MY_GATEWAY_MAX_SEND_LENGTH LITERAL1 -MY_IP_ADDRESS LITERAL1 -MY_IP_GATEWAY_ADDRESS LITERAL1 -MY_IP_RENEWAL_INTERVAL LITERAL1 -MY_IP_RENEWAL_INTERVAL_MS LITERAL1 -MY_IP_SUBNET_ADDRESS LITERAL1 -MY_MAC_ADDRESS LITERAL1 -MY_PORT LITERAL1 -MY_USE_UDP LITERAL1 - -# ESP32 - -# ESP8266 -MY_ESP8266_SERIAL_MODE LITERAL1 - -# Blacklist - autodefines that are used internally and should not be highlighted, hence commented. -# MY_CAP_ARCH -# MY_CAP_ENCR -# MY_CAP_OTA_FW -# MY_CAP_RADIO -# MY_CAP_RESET -# MY_CAP_RXBUF -# MY_CAP_SIGN -# MY_CAP_TYPE -# MY_CAPABILITIES -# MY_DEBUG_VERBOSE_CORE -# MY_GATEWAY_FEATURE -# MY_RAM_ROUTING_TABLE_ENABLED -# MY_RF24_CONFIGURATION -# MY_RFM69HW -# MY_SENSOR_NETWORK - -# Blacklist - defined in ArduinoHwSAMD and therefore not responsibility of the MySensors library -# MY_BAT_DETECT -# MY_SWC1 -# MY_SWC2 - -# Blacklist - used by the Security Personalizer, not meant to be used in any other sketch -# MY_AES_KEY -# MY_ENCRYPTION_FEATURE -# MY_HMAC_KEY -# MY_LOCK_DEVICE -# MY_LOCK_MCU -# MY_SIGNING_FEATURE -# MY_SOFT_SERIAL - -# Blacklist - internal, not meant to be used by users -# MY_EEPROM_SIZE -# MY_EXT_EEPROM_I2C_ADDRESS -# MY_EXT_EEPROM_PAGE_SIZE -# MY_EXT_EEPROM_SIZE -# MY_EXT_EEPROM_TWI_CLOCK -# MY_HW_ERR_LED_PIN -# MY_HW_RTC -# MY_HW_RTC_IRQ_HANDLER -# MY_HW_RTC_IRQN -# MY_HW_TX_LED_PIN -# MY_HWID_PADDING_BYTE -# MY_INCLUSION_BUTTON_PRESSED -# MY_IS_GATEWAY -# MY_NODE_TYPE -# MY_OTA_BOOTLOADER_MAJOR_VERSION -# MY_OTA_BOOTLOADER_MINOR_VERSION -# MY_OTA_BOOTLOADER_VERSION -# MY_SDCARD_CS - -# Blacklist - used by the Raspberry Pi gateway and not meant to be used by users -# MY_GATEWAY_LINUX -# MY_LINUX_CONFIG_FILE -# MY_LINUX_IS_SERIAL_PTY -# MY_LINUX_SERIAL_GROUPNAME -# MY_LINUX_SERIAL_IS_PTY -# MY_LINUX_SERIAL_PORT -# MY_LINUX_SERIAL_PTY - -# Blacklist - deprecated and should therefore not be highlighted anymore -# MY_LEDS_BLINKING_FEATURE -# MY_RADIO_NRF24 -# MY_RF69_IRQ_NUM -# MY_RF69_IRQ_PIN -# MY_RF69_RESET -# MY_RF69_SPI_CS -# MY_TRANSPORT_DONT_CARE_MODE -# MY_ESP8266_BSSID LITERAL1 -# MY_ESP8266_HOSTNAME LITERAL1 -# MY_ESP8266_PASSWORD LITERAL1 -# MY_ESP8266_SSID LITERAL1 -# MY_DEBUG_OTA_DISABLE_ACK - -# Blacklist - descriptional only -# MY_XYZ_POWER_PIN -# MY_MQTT_TOPIC_PREFIX - -# Blacklist - listed in https://github.com/mysensors/MySensors/issues/1107 -# Since no-one can take responsibility for them, we blacklist them so -# we can get warnings when new items are added. -# MY_AVR_TEMPERATURE_GAIN -# MY_AVR_TEMPERATURE_OFFSET -# MY_CRYPTO_SHA256_ASM -# MY_ESP32_TEMPERATURE_GAIN -# MY_ESP32_TEMPERATURE_OFFSET -# MY_NRF5_RX_BUFFER_SIZE -# MY_SAMD_TEMPERATURE_GAIN -# MY_SAMD_TEMPERATURE_OFFSET -# MY_STM32F1_TEMPERATURE_GAIN -# MY_STM32F1_TEMPERATURE_OFFSET -# MY_TRANSPORT_ENCRYPTION -# MY_OTA_I2C_ADDR -# MY_RF69_DIO5 -# MY_SERIALDEVICE diff --git a/lib/MySensors/library.json b/lib/MySensors/library.json deleted file mode 100644 index 6c29ab35..00000000 --- a/lib/MySensors/library.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "MySensors", - "keywords": "framework, sensor, rf", - "description": "Home Automation Framework. Create your own wireless sensor mesh using nRF24L01+, RFM69 and RFM95 radios running on AVR, ESP32, ESP8266, NRF5x, SAMD, STM32F1 and Teensyduino. Over-the-air updates and MySensors support by 20+ home automation controllers.", - "repository": - { - "type": "git", - "url": "https://github.com/mysensors/MySensors.git" - }, - "version": "2.3.2", - "frameworks": "arduino", - "platforms": "*", - "export": { - "exclude": [ - "tests", - "Documentation", - ".mystools", - "projects", - "examples_linux", - "initscripts", - "configure", - ".ci", - "Doxyfile" - ] - } -} diff --git a/lib/MySensors/library.properties b/lib/MySensors/library.properties deleted file mode 100644 index 2354fe60..00000000 --- a/lib/MySensors/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=MySensors -version=2.3.2 -author=The MySensors Team -maintainer=The MySensors Team -sentence=Home Automation Framework -paragraph=Create your own wireless sensor mesh using nRF24L01+, RFM69 and RFM95 radios running on AVR, ESP32, ESP8266, NRF5x, SAMD, STM32F1 and Teensyduino. Over-the-air updates and MySensors support by 20+ home automation controllers. -category=Communication -url=https://www.mysensors.org -architectures=* diff --git a/src/modules/exec/MySensors/MySensorsData.cpp b/src/MySensorsData.cpp similarity index 100% rename from src/modules/exec/MySensors/MySensorsData.cpp rename to src/MySensorsData.cpp diff --git a/src/modules/exec/MySensors/modinfo.json b/src/modules/exec/MySensors/modinfo.json index 63b8c4bc..35f22de2 100644 --- a/src/modules/exec/MySensors/modinfo.json +++ b/src/modules/exec/MySensors/modinfo.json @@ -37,6 +37,8 @@ }, "defActive": true, "usedLibs": { - "esp32_4mb": [] + "esp32_4mb": [ + "MySensors@2.3.2" + ] } } \ No newline at end of file