1052 lines
30 KiB
C++
Raw Normal View History

/*
* EBYTE LoRa E2200 Series
* https://www.mischianti.org/category/my-libraries/lora-e220-devices/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Renzo Mischianti www.mischianti.org All right reserved.
*
* You may copy, alter and reuse this code in any way you like, but please leave
* reference to www.mischianti.org in your comments if you redistribute this code.
*
*
* 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.
*/
#include "LoRa_E220.h"
#ifdef ACTIVATE_SOFTWARE_SERIAL
LoRa_E220::LoRa_E220(byte txE220pin, byte rxE220pin, UART_BPS_RATE bpsRate){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
SoftwareSerial* mySerial = new SoftwareSerial((uint8_t)this->txE220pin, (uint8_t)this->rxE220pin); // "RX TX" // @suppress("Abstract class cannot be instantiated")
this->ss = mySerial;
this->hs = NULL;
this->bpsRate = bpsRate;
}
LoRa_E220::LoRa_E220(byte txE220pin, byte rxE220pin, byte auxPin, UART_BPS_RATE bpsRate){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->auxPin = auxPin;
SoftwareSerial* mySerial = new SoftwareSerial((uint8_t)this->txE220pin, (uint8_t)this->rxE220pin); // "RX TX" // @suppress("Abstract class cannot be instantiated")
this->ss = mySerial;
this->hs = NULL;
this->bpsRate = bpsRate;
}
LoRa_E220::LoRa_E220(byte txE220pin, byte rxE220pin, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->auxPin = auxPin;
this->m0Pin = m0Pin;
this->m1Pin = m1Pin;
SoftwareSerial* mySerial = new SoftwareSerial((uint8_t)this->txE220pin, (uint8_t)this->rxE220pin); // "RX TX" // @suppress("Abstract class cannot be instantiated")
this->ss = mySerial;
this->hs = NULL;
this->bpsRate = bpsRate;
}
#endif
LoRa_E220::LoRa_E220(HardwareSerial* serial, UART_BPS_RATE bpsRate){ //, uint32_t serialConfig
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
#ifdef ACTIVATE_SOFTWARE_SERIAL
this->ss = NULL;
#endif
this->hs = serial;
// this->serialConfig = serialConfig;
this->bpsRate = bpsRate;
}
LoRa_E220::LoRa_E220(HardwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate){ // , uint32_t serialConfig
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->auxPin = auxPin;
#ifdef ACTIVATE_SOFTWARE_SERIAL
this->ss = NULL;
#endif
this->hs = serial;
// this->serialConfig = serialConfig;
this->bpsRate = bpsRate;
}
LoRa_E220::LoRa_E220(HardwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate){ //, uint32_t serialConfig
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->auxPin = auxPin;
this->m0Pin = m0Pin;
this->m1Pin = m1Pin;
#ifdef ACTIVATE_SOFTWARE_SERIAL
this->ss = NULL;
#endif
this->hs = serial;
// this->serialConfig = serialConfig;
this->bpsRate = bpsRate;
}
#ifdef HARDWARE_SERIAL_SELECTABLE_PIN
LoRa_E220::LoRa_E220(byte txE220pin, byte rxE220pin, HardwareSerial* serial, UART_BPS_RATE bpsRate, uint32_t serialConfig){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
#ifdef ACTIVATE_SOFTWARE_SERIAL
this->ss = NULL;
#endif
this->serialConfig = serialConfig;
this->hs = serial;
this->bpsRate = bpsRate;
}
LoRa_E220::LoRa_E220(byte txE220pin, byte rxE220pin, HardwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate, uint32_t serialConfig){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->auxPin = auxPin;
#ifdef ACTIVATE_SOFTWARE_SERIAL
this->ss = NULL;
#endif
this->serialConfig = serialConfig;
this->hs = serial;
this->bpsRate = bpsRate;
}
LoRa_E220::LoRa_E220(byte txE220pin, byte rxE220pin, HardwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate, uint32_t serialConfig){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->auxPin = auxPin;
this->m0Pin = m0Pin;
this->m1Pin = m1Pin;
#ifdef ACTIVATE_SOFTWARE_SERIAL
this->ss = NULL;
#endif
this->serialConfig = serialConfig;
this->hs = serial;
this->bpsRate = bpsRate;
}
#endif
#ifdef ACTIVATE_SOFTWARE_SERIAL
LoRa_E220::LoRa_E220(SoftwareSerial* serial, UART_BPS_RATE bpsRate){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->ss = serial;
this->hs = NULL;
this->bpsRate = bpsRate;
}
LoRa_E220::LoRa_E220(SoftwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->auxPin = auxPin;
this->ss = serial;
this->hs = NULL;
this->bpsRate = bpsRate;
}
LoRa_E220::LoRa_E220(SoftwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate){
this->txE220pin = txE220pin;
this->rxE220pin = rxE220pin;
this->auxPin = auxPin;
this->m0Pin = m0Pin;
this->m1Pin = m1Pin;
this->ss = serial;
this->hs = NULL;
this->bpsRate = bpsRate;
}
#endif
bool LoRa_E220::begin(){
DEBUG_PRINT("RX MIC ---> ");
DEBUG_PRINTLN(this->txE220pin);
DEBUG_PRINT("TX MIC ---> ");
DEBUG_PRINTLN(this->rxE220pin);
DEBUG_PRINT("AUX ---> ");
DEBUG_PRINTLN(this->auxPin);
DEBUG_PRINT("M0 ---> ");
DEBUG_PRINTLN(this->m0Pin);
DEBUG_PRINT("M1 ---> ");
DEBUG_PRINTLN(this->m1Pin);
if (this->auxPin != -1) {
pinMode(this->auxPin, INPUT);
DEBUG_PRINTLN("Init AUX pin!");
}
if (this->m0Pin != -1) {
// pinMode(this->m0Pin, OUTPUT);
DEBUG_PRINTLN("Init M0 pin!");
setMPins(this->m0Pin, HIGH);
}
if (this->m1Pin != -1) {
pinMode(this->m1Pin, OUTPUT);
DEBUG_PRINTLN("Init M1 pin!");
setMPins(this->m1Pin, HIGH);
}
DEBUG_PRINTLN("Begin ex");
if (this->hs){
DEBUG_PRINTLN("Begin Hardware Serial");
#ifdef HARDWARE_SERIAL_SELECTABLE_PIN
if(this->txE220pin != -1 && this->rxE220pin != -1) {
DEBUG_PRINTLN("PIN SELECTED!!");
this->serialDef.begin(*this->hs, this->bpsRate, this->serialConfig, this->txE220pin, this->rxE220pin);
}else{
this->serialDef.begin(*this->hs, this->bpsRate, this->serialConfig);
}
#endif
#ifndef HARDWARE_SERIAL_SELECTABLE_PIN
this->serialDef.begin(*this->hs, this->bpsRate);
#endif
while (!this->hs) {
; // wait for serial port to connect. Needed for native USB
}
#ifdef ACTIVATE_SOFTWARE_SERIAL
}else if (this->ss){
DEBUG_PRINTLN("Begin Software Serial");
this->serialDef.begin(*this->ss, this->bpsRate);
} else{
DEBUG_PRINTLN("Begin Software Serial Pin");
SoftwareSerial* mySerial = new SoftwareSerial((int)this->txE220pin, (int)this->rxE220pin); // "RX TX" // @suppress("Abstract class cannot be instantiated")
this->ss = mySerial;
// SoftwareSerial mySerial(this->txE220pin, this->rxE220pin);
DEBUG_PRINT("RX Pin: ");
DEBUG_PRINT((int)this->txE220pin);
DEBUG_PRINT("TX Pin: ");
DEBUG_PRINTLN((int)this->rxE220pin);
this->serialDef.begin(*this->ss, this->bpsRate);
#endif
}
this->serialDef.stream->setTimeout(100);
Status status = setMode(MODE_0_NORMAL);
2023-04-12 22:47:17 +02:00
return status;
}
/*
Utility method to wait until module is doen tranmitting
a timeout is provided to avoid an infinite loop
*/
Status LoRa_E220::waitCompleteResponse(unsigned long timeout, unsigned int waitNoAux) {
Status result = E220_SUCCESS;
unsigned long t = millis();
// make darn sure millis() is not about to reach max data type limit and start over
if (((unsigned long) (t + timeout)) == 0){
t = 0;
}
// if AUX pin was supplied and look for HIGH state
// note you can omit using AUX if no pins are available, but you will have to use delay() to let module finish
if (this->auxPin != -1) {
while (digitalRead(this->auxPin) == LOW) {
if ((millis() - t) > timeout){
result = ERR_E220_TIMEOUT;
DEBUG_PRINTLN("Timeout error!");
return result;
}
}
DEBUG_PRINTLN("AUX HIGH!");
}
else {
// if you can't use aux pin, use 4K7 pullup with Arduino
// you may need to adjust this value if transmissions fail
this->managedDelay(waitNoAux);
DEBUG_PRINTLN(F("Wait no AUX pin!"));
}
// per data sheet control after aux goes high is 2ms so delay for at least that long)
this->managedDelay(20);
DEBUG_PRINTLN(F("Complete!"));
return result;
}
/*
delay() in a library is not a good idea as it can stop interrupts
just poll internal time until timeout is reached
*/
void LoRa_E220::managedDelay(unsigned long timeout) {
unsigned long t = millis();
// make darn sure millis() is not about to reach max data type limit and start over
if (((unsigned long) (t + timeout)) == 0){
t = 0;
}
while ((millis() - t) < timeout) { }
}
/*
Method to indicate availability
*/
//int LoRa_E220::available(unsigned long timeout) {
int LoRa_E220::available() {
// unsigned long t = millis();
//
// // make darn sure millis() is not about to reach max data type limit and start over
// if (((unsigned long) (t + timeout)) == 0){
// t = 0;
// }
//
// if (this->auxPin != -1) {
// if (digitalRead(this->auxPin) == HIGH){
// return 0;
// }else{
// while (digitalRead(this->auxPin) == LOW) {
// if ((millis() - t) > timeout){
// DEBUG_PRINTLN("Timeout error!");
// return 0;
// }
// }
// DEBUG_PRINTLN("AUX HIGH!");
// return 2;
// }
// }else{
return this->serialDef.stream->available();
// }
}
/*
Method to indicate availability
*/
void LoRa_E220::flush() {
this->serialDef.stream->flush();
}
void LoRa_E220::cleanUARTBuffer()
{
// bool IsNull = true;
while (this->available())
{
// IsNull = false;
this->serialDef.stream->read();
}
}
/*
Method to send a chunk of data provided data is in a struct--my personal favorite as you
need not parse or worry about sprintf() inability to handle floats
TTP: put your structure definition into a .h file and include in both the sender and reciever
sketches
NOTE: of your sender and receiver MCU's are different (Teensy and Arduino) caution on the data
types each handle ints floats differently
*/
Status LoRa_E220::sendStruct(void *structureManaged, uint16_t size_) {
if (size_ > MAX_SIZE_TX_PACKET + 2){
return ERR_E220_PACKET_TOO_BIG;
}
Status result = E220_SUCCESS;
uint8_t len = this->serialDef.stream->write((uint8_t *) structureManaged, size_);
if (len!=size_){
DEBUG_PRINT(F("Send... len:"))
DEBUG_PRINT(len);
DEBUG_PRINT(F(" size:"))
DEBUG_PRINT(size_);
if (len==0){
result = ERR_E220_NO_RESPONSE_FROM_DEVICE;
}else{
result = ERR_E220_DATA_SIZE_NOT_MATCH;
}
}
if (result != E220_SUCCESS) return result;
result = this->waitCompleteResponse(5000, 5000);
if (result != E220_SUCCESS) return result;
DEBUG_PRINT(F("Clear buffer..."))
this->cleanUARTBuffer();
DEBUG_PRINTLN(F("ok!"))
return result;
}
/*
Method to get a chunk of data provided data is in a struct--my personal favorite as you
need not parse or worry about sprintf() inability to handle floats
TTP: put your structure definition into a .h file and include in both the sender and reciever
sketches
NOTE: of your sender and receiver MCU's are different (Teensy and Arduino) caution on the data
types each handle ints floats differently
*/
Status LoRa_E220::receiveStruct(void *structureManaged, uint16_t size_) {
Status result = E220_SUCCESS;
uint8_t len = this->serialDef.stream->readBytes((uint8_t *) structureManaged, size_);
DEBUG_PRINT("Available buffer: ");
DEBUG_PRINT(len);
DEBUG_PRINT(" structure size: ");
DEBUG_PRINTLN(size_);
if (len!=size_){
if (len==0){
result = ERR_E220_NO_RESPONSE_FROM_DEVICE;
}else{
result = ERR_E220_DATA_SIZE_NOT_MATCH;
}
}
if (result != E220_SUCCESS) return result;
result = this->waitCompleteResponse(1000);
if (result != E220_SUCCESS) return result;
return result;
}
/*
method to set the mode (program, normal, etc.)
*/
Status LoRa_E220::setMode(MODE_TYPE mode) {
// data sheet claims module needs some extra time after mode setting (2ms)
// most of my projects uses 10 ms, but 40ms is safer
this->managedDelay(40);
if (this->m0Pin == -1 && this->m1Pin == -1) {
DEBUG_PRINTLN(F("The M0 and M1 pins is not set, this mean that you are connect directly the pins as you need!"))
}else{
switch (mode)
{
case MODE_0_NORMAL:
// Mode 0 | normal operation
setMPins(this->m0Pin, LOW);
setMPins(this->m1Pin, LOW);
DEBUG_PRINTLN("MODE NORMAL!");
break;
case MODE_1_WOR_TRANSMITTER:
setMPins(this->m0Pin, HIGH);
setMPins(this->m1Pin, LOW);
DEBUG_PRINTLN("MODE WOR!");
break;
case MODE_2_WOR_RECEIVER:
// case MODE_2_PROGRAM:
setMPins(this->m0Pin, LOW);
setMPins(this->m1Pin, HIGH);
DEBUG_PRINTLN("MODE RECEIVING!");
break;
case MODE_3_CONFIGURATION:
// Mode 3 | Setting operation
setMPins(this->m0Pin, HIGH);
setMPins(this->m1Pin, HIGH);
DEBUG_PRINTLN("MODE SLEEP CONFIG!");
break;
default:
return ERR_E220_INVALID_PARAM;
}
}
// data sheet says 2ms later control is returned, let's give just a bit more time
// these modules can take time to activate pins
this->managedDelay(40);
// wait until aux pin goes back low
Status res = this->waitCompleteResponse(1000);
if (res == E220_SUCCESS){
this->mode = mode;
}
return res;
}
MODE_TYPE LoRa_E220::getMode(){
return this->mode;
}
void LoRa_E220::writeProgramCommand(PROGRAM_COMMAND cmd, REGISTER_ADDRESS addr, PACKET_LENGHT pl){
uint8_t CMD[3] = {cmd, addr, pl};
uint8_t size = this->serialDef.stream->write(CMD, 3);
DEBUG_PRINTLN(size);
this->managedDelay(50); //need ti check
}
ResponseStructContainer LoRa_E220::getConfiguration(){
ResponseStructContainer rc;
rc.status.code = checkUARTConfiguration(MODE_3_PROGRAM);
if (rc.status.code!=E220_SUCCESS) return rc;
MODE_TYPE prevMode = this->mode;
rc.status.code = this->setMode(MODE_3_PROGRAM);
if (rc.status.code!=E220_SUCCESS) return rc;
this->writeProgramCommand(READ_CONFIGURATION, REG_ADDRESS_CFG, PL_CONFIGURATION);
rc.data = malloc(sizeof(Configuration));
rc.status.code = this->receiveStruct((uint8_t *)rc.data, sizeof(Configuration));
#ifdef LoRa_E220_DEBUG
this->printParameters((Configuration *)rc.data);
#endif
if (rc.status.code!=E220_SUCCESS) {
this->setMode(prevMode);
return rc;
}
rc.status.code = this->setMode(prevMode);
if (rc.status.code!=E220_SUCCESS) return rc;
if (WRONG_FORMAT == ((Configuration *)rc.data)->COMMAND){
rc.status.code = ERR_E220_WRONG_FORMAT;
}
if (RETURNED_COMMAND != ((Configuration *)rc.data)->COMMAND || REG_ADDRESS_CFG!= ((Configuration *)rc.data)->STARTING_ADDRESS || PL_CONFIGURATION!= ((Configuration *)rc.data)->LENGHT){
rc.status.code = ERR_E220_HEAD_NOT_RECOGNIZED;
}
return rc;
}
RESPONSE_STATUS LoRa_E220::checkUARTConfiguration(MODE_TYPE mode){
if (mode==MODE_3_PROGRAM && this->bpsRate!=UART_BPS_RATE_9600){
return ERR_E220_WRONG_UART_CONFIG;
}
return E220_SUCCESS;
}
ResponseStatus LoRa_E220::setConfiguration(Configuration configuration, PROGRAM_COMMAND saveType){
ResponseStatus rc;
rc.code = checkUARTConfiguration(MODE_3_PROGRAM);
if (rc.code!=E220_SUCCESS) return rc;
MODE_TYPE prevMode = this->mode;
rc.code = this->setMode(MODE_3_PROGRAM);
if (rc.code!=E220_SUCCESS) return rc;
// this->writeProgramCommand(saveType, REG_ADDRESS_CFG);
// configuration.HEAD = saveType;
configuration.COMMAND = saveType;
configuration.STARTING_ADDRESS = REG_ADDRESS_CFG;
configuration.LENGHT = PL_CONFIGURATION;
rc.code = this->sendStruct((uint8_t *)&configuration, sizeof(Configuration));
if (rc.code!=E220_SUCCESS) {
this->setMode(prevMode);
return rc;
}
rc.code = this->receiveStruct((uint8_t *)&configuration, sizeof(Configuration));
#ifdef LoRa_E220_DEBUG
this->printParameters((Configuration *)&configuration);
#endif
rc.code = this->setMode(prevMode);
if (rc.code!=E220_SUCCESS) return rc;
if (WRONG_FORMAT == ((Configuration *)&configuration)->COMMAND){
rc.code = ERR_E220_WRONG_FORMAT;
}
if (RETURNED_COMMAND != ((Configuration *)&configuration)->COMMAND || REG_ADDRESS_CFG!= ((Configuration *)&configuration)->STARTING_ADDRESS || PL_CONFIGURATION!= ((Configuration *)&configuration)->LENGHT){
rc.code = ERR_E220_HEAD_NOT_RECOGNIZED;
}
return rc;
}
ResponseStructContainer LoRa_E220::getModuleInformation(){
ResponseStructContainer rc;
rc.status.code = checkUARTConfiguration(MODE_3_PROGRAM);
if (rc.status.code!=E220_SUCCESS) return rc;
MODE_TYPE prevMode = this->mode;
rc.status.code = this->setMode(MODE_3_PROGRAM);
if (rc.status.code!=E220_SUCCESS) return rc;
this->writeProgramCommand(READ_CONFIGURATION, REG_ADDRESS_PID, PL_PID);
rc.data = malloc(sizeof(ModuleInformation));
// struct ModuleInformation *moduleInformation = (ModuleInformation *)malloc(sizeof(ModuleInformation));
rc.status.code = this->receiveStruct((uint8_t *)rc.data, sizeof(ModuleInformation));
if (rc.status.code!=E220_SUCCESS) {
this->setMode(prevMode);
return rc;
}
rc.status.code = this->setMode(prevMode);
if (rc.status.code!=E220_SUCCESS) return rc;
// this->printParameters(*configuration);
if (WRONG_FORMAT == ((ModuleInformation *)rc.data)->COMMAND){
rc.status.code = ERR_E220_WRONG_FORMAT;
}
if (RETURNED_COMMAND != ((ModuleInformation *)rc.data)->COMMAND || REG_ADDRESS_PID!= ((ModuleInformation *)rc.data)->STARTING_ADDRESS || PL_PID!= ((ModuleInformation *)rc.data)->LENGHT){
rc.status.code = ERR_E220_HEAD_NOT_RECOGNIZED;
}
DEBUG_PRINTLN("----------------------------------------");
DEBUG_PRINT(F("HEAD: ")); DEBUG_PRINT(((ModuleInformation *)rc.data)->COMMAND, BIN);DEBUG_PRINT(" ");DEBUG_PRINT(((ModuleInformation *)rc.data)->STARTING_ADDRESS, DEC);DEBUG_PRINT(" ");DEBUG_PRINTLN(((ModuleInformation *)rc.data)->LENGHT, HEX);
DEBUG_PRINT(F("Model no.: ")); DEBUG_PRINTLN(((ModuleInformation *)rc.data)->model, HEX);
DEBUG_PRINT(F("Version : ")); DEBUG_PRINTLN(((ModuleInformation *)rc.data)->version, HEX);
DEBUG_PRINT(F("Features : ")); DEBUG_PRINTLN(((ModuleInformation *)rc.data)->features, HEX);
DEBUG_PRINT(F("Status : ")); DEBUG_PRINTLN(rc.status.getResponseDescription());
DEBUG_PRINTLN("----------------------------------------");
// if (rc.status.code!=E220_SUCCESS) return rc;
// rc.data = moduleInformation; // malloc(sizeof (moduleInformation));
return rc;
}
ResponseStatus LoRa_E220::resetModule(){
// ResponseStatus status;
//
// status.code = checkUARTConfiguration(MODE_2_PROGRAM);
// if (status.code!=E220_SUCCESS) return status;
//
// MODE_TYPE prevMode = this->mode;
//
// status.code = this->setMode(MODE_2_PROGRAM);
// if (status.code!=E220_SUCCESS) return status;
//
// this->writeProgramCommand(WRITE_RESET_MODULE);
//
// status.code = this->waitCompleteResponse(1000);
// if (status.code!=E220_SUCCESS) {
// this->setMode(prevMode);
// return status;
// }
//
//
// status.code = this->setMode(prevMode);
// if (status.code!=E220_SUCCESS) return status;
//
// return status;
DEBUG_PRINT(F("No information to reset module!"));
ResponseStatus status;
status.code = ERR_E220_NOT_IMPLEMENT;
return status;
}
ResponseContainer LoRa_E220::receiveMessage(){
return LoRa_E220::receiveMessageComplete(false);
}
ResponseContainer LoRa_E220::receiveMessageRSSI(){
return LoRa_E220::receiveMessageComplete(true);
}
ResponseContainer LoRa_E220::receiveMessageComplete(bool rssiEnabled){
ResponseContainer rc;
rc.status.code = E220_SUCCESS;
String tmpData = this->serialDef.stream->readString();
DEBUG_PRINTLN(tmpData);
if (rssiEnabled){
rc.rssi = tmpData.charAt(tmpData.length()-1);
rc.data = tmpData.substring(0, tmpData.length()-1);
}else{
rc.data = tmpData;
}
this->cleanUARTBuffer();
if (rc.status.code!=E220_SUCCESS) {
return rc;
}
// rc.data = message; // malloc(sizeof (moduleInformation));
return rc;
}
ResponseContainer LoRa_E220::receiveMessageUntil(char delimiter){
ResponseContainer rc;
rc.status.code = E220_SUCCESS;
rc.data = this->serialDef.stream->readStringUntil(delimiter);
// this->cleanUARTBuffer();
if (rc.status.code!=E220_SUCCESS) {
return rc;
}
// rc.data = message; // malloc(sizeof (moduleInformation));
return rc;
}
ResponseContainer LoRa_E220::receiveInitialMessage(uint8_t size){
ResponseContainer rc;
rc.status.code = E220_SUCCESS;
char buff[size];
uint8_t len = this->serialDef.stream->readBytes(buff, size);
if (len!=size) {
if (len==0){
rc.status.code = ERR_E220_NO_RESPONSE_FROM_DEVICE;
}else{
rc.status.code = ERR_E220_DATA_SIZE_NOT_MATCH;
}
return rc;
}
rc.data = buff; // malloc(sizeof (moduleInformation));
return rc;
}
ResponseStructContainer LoRa_E220::receiveMessage(const uint8_t size){
return LoRa_E220::receiveMessageComplete(size, false);
}
ResponseStructContainer LoRa_E220::receiveMessageRSSI(const uint8_t size){
return LoRa_E220::receiveMessageComplete(size, true);
}
ResponseStructContainer LoRa_E220::receiveMessageComplete(const uint8_t size, bool rssiEnabled){
ResponseStructContainer rc;
rc.data = malloc(size);
rc.status.code = this->receiveStruct((uint8_t *)rc.data, size);
if (rc.status.code!=E220_SUCCESS) {
return rc;
}
if (rssiEnabled){
char rssi[1];
this->serialDef.stream->readBytes(rssi, 1);
rc.rssi = rssi[0];
}
this->cleanUARTBuffer();
return rc;
}
ResponseStatus LoRa_E220::sendMessage(const void *message, const uint8_t size){
ResponseStatus status;
status.code = this->sendStruct((uint8_t *)message, size);
if (status.code!=E220_SUCCESS) return status;
return status;
}
ResponseStatus LoRa_E220::sendMessage(const String message){
DEBUG_PRINT(F("Send message: "));
DEBUG_PRINT(message);
byte size = message.length(); // sizeof(message.c_str())+1;
DEBUG_PRINT(F(" size: "));
DEBUG_PRINTLN(size);
char messageFixed[size];
memcpy(messageFixed,message.c_str(),size);
DEBUG_PRINTLN(F(" memcpy "));
ResponseStatus status;
status.code = this->sendStruct((uint8_t *)&messageFixed, size);
if (status.code!=E220_SUCCESS) return status;
// free(messageFixed);
return status;
}
ResponseStatus LoRa_E220::sendFixedMessage(byte ADDH, byte ADDL, byte CHAN, const String message){
// DEBUG_PRINT("String/size: ");
// DEBUG_PRINT(message);
// DEBUG_PRINT("/");
byte size = message.length(); // sizeof(message.c_str())+1;
// DEBUG_PRINTLN(size);
//
// #pragma pack(push, 1)
// struct FixedStransmissionString {
// byte ADDH = 0;
// byte ADDL = 0;
// byte CHAN = 0;
// char message[];
// } fixedStransmission;
// #pragma pack(pop)
//
// fixedStransmission.ADDH = ADDH;
// fixedStransmission.ADDL = ADDL;
// fixedStransmission.CHAN = CHAN;
// char* msg = (char*)message.c_str();
// memcpy(fixedStransmission.message, (char*)msg, size);
//// fixedStransmission.message = message;
//
// DEBUG_PRINT("Message: ");
// DEBUG_PRINTLN(fixedStransmission.message);
//
// ResponseStatus status;
// status.code = this->sendStruct((uint8_t *)&fixedStransmission, sizeof(fixedStransmission));
// if (status.code!=E220_SUCCESS) return status;
//
// return status;
char messageFixed[size];
memcpy(messageFixed,message.c_str(),size);
return this->sendFixedMessage(ADDH, ADDL, CHAN, (uint8_t *)messageFixed, size);
}
ResponseStatus LoRa_E220::sendBroadcastFixedMessage(byte CHAN, const String message){
return this->sendFixedMessage(BROADCAST_ADDRESS, BROADCAST_ADDRESS, CHAN, message);
}
typedef struct fixedStransmission
{
byte ADDH = 0;
byte ADDL = 0;
byte CHAN = 0;
unsigned char message[];
}FixedStransmission;
FixedStransmission *init_stack(int m){
FixedStransmission *st = (FixedStransmission *)malloc(sizeof(FixedStransmission)+m*sizeof(int));
return st;
}
ResponseStatus LoRa_E220::sendFixedMessage( byte ADDH,byte ADDL, byte CHAN, const void *message, const uint8_t size){
// #pragma pack(push, 1)
// struct FixedStransmission {
// byte ADDH = 0;
// byte ADDL = 0;
// byte CHAN = 0;
// unsigned char message[];
// } fixedStransmission;
// #pragma pack(pop)
DEBUG_PRINT(ADDH);
FixedStransmission *fixedStransmission = init_stack(size);
// STACK *resize_stack(STACK *st, int m){
// if (m<=st->max){
// return st; /* Take sure do not kill old values */
// }
// STACK *st = (STACK *)realloc(sizeof(STACK)+m*sizeof(int));
// st->max = m;
// return st;
// }
fixedStransmission->ADDH = ADDH;
fixedStransmission->ADDL = ADDL;
fixedStransmission->CHAN = CHAN;
// fixedStransmission.message = &message;
memcpy(fixedStransmission->message,(unsigned char*)message,size);
ResponseStatus status;
status.code = this->sendStruct((uint8_t *)fixedStransmission, size+3);
free(fixedStransmission);
if (status.code!=E220_SUCCESS) return status;
return status;
}
ConfigurationMessage *init_stack_conf(int m){
ConfigurationMessage *st = (ConfigurationMessage *)malloc(sizeof(ConfigurationMessage)+m*sizeof(int));
return st;
}
ResponseStatus LoRa_E220::sendConfigurationMessage( byte ADDH,byte ADDL, byte CHAN, Configuration *configuration, PROGRAM_COMMAND programCommand){
ResponseStatus rc;
// rc.code = this->setMode(MODE_2_PROGRAM);
// if (rc.code!=E220_SUCCESS) return rc;
configuration->COMMAND = programCommand;
configuration->STARTING_ADDRESS = REG_ADDRESS_CFG;
configuration->LENGHT = PL_CONFIGURATION;
ConfigurationMessage *fixedStransmission = init_stack_conf(sizeof(Configuration));
// fixedStransmission.message = &message;
memcpy(fixedStransmission->message,(unsigned char*)configuration,sizeof(Configuration));
fixedStransmission->specialCommand1 = SPECIAL_WIFI_CONF_COMMAND;
fixedStransmission->specialCommand2 = SPECIAL_WIFI_CONF_COMMAND;
DEBUG_PRINTLN(sizeof(Configuration)+2);
rc = sendFixedMessage(ADDH, ADDL, CHAN, fixedStransmission, sizeof(Configuration)+2);
//
// ResponseStatus status;
// status.code = this->sendStruct((uint8_t *)fixedStransmission, sizeof(Configuration)+5);
// if (status.code!=E220_SUCCESS) return status;
// free(fixedStransmission);
return rc;
}
ResponseStatus LoRa_E220::sendBroadcastFixedMessage(byte CHAN, const void *message, const uint8_t size){
return this->sendFixedMessage(0xFF, 0xFF, CHAN, message, size);
}
#define KeeLoq_NLF 0x3A5C742E
unsigned long LoRa_E220::encrypt(unsigned long data)
{
unsigned long x = data;
unsigned long r;
int keyBitNo, index;
unsigned long keyBitVal,bitVal;
for (r = 0; r < 528; r++)
{
keyBitNo = r & 63;
if(keyBitNo < 32)
keyBitVal = bitRead(this->halfKeyloqKey,keyBitNo); // key low
else
keyBitVal = bitRead(this->halfKeyloqKey, keyBitNo - 32);// key hight
index = 1 * bitRead(x,1) + 2 * bitRead(x,9) + 4 * bitRead(x,20) + 8 * bitRead(x,26) + 16 * bitRead(x,31);
bitVal = bitRead(x,0) ^ bitRead(x, 16) ^ bitRead(KeeLoq_NLF,index) ^ keyBitVal;
x = (x>>1) ^ bitVal<<31;
}
return x;
}
unsigned long LoRa_E220::decrypt(unsigned long data)
{
unsigned long x = data;
unsigned long r;
int keyBitNo, index;
unsigned long keyBitVal,bitVal;
for (r = 0; r < 528; r++)
{
keyBitNo = (15-r) & 63;
if(keyBitNo < 32)
keyBitVal = bitRead(this->halfKeyloqKey,keyBitNo); // key low
else
keyBitVal = bitRead(this->halfKeyloqKey, keyBitNo - 32); // key hight
index = 1 * bitRead(x,0) + 2 * bitRead(x,8) + 4 * bitRead(x,19) + 8 * bitRead(x,25) + 16 * bitRead(x,30);
bitVal = bitRead(x,31) ^ bitRead(x, 15) ^ bitRead(KeeLoq_NLF,index) ^ keyBitVal;
x = (x<<1) ^ bitVal;
}
return x;
}
#ifdef LoRa_E220_DEBUG
void LoRa_E220::printParameters(struct Configuration *configuration) {
DEBUG_PRINTLN("----------------------------------------");
DEBUG_PRINT(F("HEAD : ")); DEBUG_PRINT(configuration->COMMAND, HEX);DEBUG_PRINT(" ");DEBUG_PRINT(configuration->STARTING_ADDRESS, HEX);DEBUG_PRINT(" ");DEBUG_PRINTLN(configuration->LENGHT, HEX);
DEBUG_PRINTLN(F(" "));
DEBUG_PRINT(F("AddH : ")); DEBUG_PRINTLN(configuration->ADDH, HEX);
DEBUG_PRINT(F("AddL : ")); DEBUG_PRINTLN(configuration->ADDL, HEX);
DEBUG_PRINTLN(F(" "));
DEBUG_PRINT(F("Chan : ")); DEBUG_PRINT(configuration->CHAN, DEC); DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->getChannelDescription());
DEBUG_PRINTLN(F(" "));
DEBUG_PRINT(F("SpeedParityBit : ")); DEBUG_PRINT(configuration->SPED.uartParity, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->SPED.getUARTParityDescription());
DEBUG_PRINT(F("SpeedUARTDatte : ")); DEBUG_PRINT(configuration->SPED.uartBaudRate, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->SPED.getUARTBaudRateDescription());
DEBUG_PRINT(F("SpeedAirDataRate : ")); DEBUG_PRINT(configuration->SPED.airDataRate, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->SPED.getAirDataRateDescription());
DEBUG_PRINTLN(F(" "));
DEBUG_PRINT(F("OptionSubPacketSett: ")); DEBUG_PRINT(configuration->OPTION.subPacketSetting, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->OPTION.getSubPacketSetting());
DEBUG_PRINT(F("OptionTranPower : ")); DEBUG_PRINT(configuration->OPTION.transmissionPower, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->OPTION.getTransmissionPowerDescription());
DEBUG_PRINT(F("OptionRSSIAmbientNo: ")); DEBUG_PRINT(configuration->OPTION.RSSIAmbientNoise, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->OPTION.getRSSIAmbientNoiseEnable());
DEBUG_PRINTLN(F(" "));
DEBUG_PRINT(F("TransModeWORPeriod : ")); DEBUG_PRINT(configuration->TRANSMISSION_MODE.WORPeriod, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->TRANSMISSION_MODE.getWORPeriodByParamsDescription());
DEBUG_PRINT(F("TransModeEnableLBT : ")); DEBUG_PRINT(configuration->TRANSMISSION_MODE.enableLBT, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->TRANSMISSION_MODE.getLBTEnableByteDescription());
DEBUG_PRINT(F("TransModeEnableRSSI: ")); DEBUG_PRINT(configuration->TRANSMISSION_MODE.enableRSSI, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->TRANSMISSION_MODE.getRSSIEnableByteDescription());
DEBUG_PRINT(F("TransModeFixedTrans: ")); DEBUG_PRINT(configuration->TRANSMISSION_MODE.fixedTransmission, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->TRANSMISSION_MODE.getFixedTransmissionDescription());
DEBUG_PRINTLN("----------------------------------------");
}
#endif