6 changed files with 1706 additions and 26 deletions
-
681LoRa_E32.cpp
-
298LoRa_E32.h
-
3OpenFlightTX.h
-
296OpenFlightTX.ino
-
2README.md
-
452statesNaming.h
@ -0,0 +1,681 @@ |
|||||
|
#include "LoRa_E32.h"
|
||||
|
|
||||
|
LoRa_E32::LoRa_E32(HardwareSerial hs) { |
||||
|
/**** For RX ****
|
||||
|
this->auxPin = 4; |
||||
|
this->m0Pin = 18; |
||||
|
this->m1Pin = 5; |
||||
|
*/ |
||||
|
|
||||
|
this->auxPin = 4; |
||||
|
this->m0Pin = 2; |
||||
|
this->m1Pin = 5; |
||||
|
|
||||
|
this->hs = &Serial2; |
||||
|
this->bpsRate = UART_BPS_RATE_9600; |
||||
|
// this->bpsRate = UART_BPS_RATE_115200;
|
||||
|
} |
||||
|
|
||||
|
bool LoRa_E32::begin(){ |
||||
|
pinMode(this->auxPin, INPUT); |
||||
|
pinMode(this->m0Pin, OUTPUT); |
||||
|
pinMode(this->m1Pin, OUTPUT); |
||||
|
digitalWrite(this->m0Pin, HIGH); |
||||
|
digitalWrite(this->m1Pin, HIGH); |
||||
|
|
||||
|
if (this->hs){ |
||||
|
this->serialDef.begin(*this->hs, this->bpsRate, this->serialConfig); |
||||
|
while (!this->hs) { |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
this->serialDef.stream->setTimeout(1000); |
||||
|
Status status = setMode(MODE_0_NORMAL); |
||||
|
return status==SUCCESS; |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* Utility method to wait until module is doen tranmitting |
||||
|
* a timeout is provided to avoid an infinite loop |
||||
|
*/ |
||||
|
Status LoRa_E32::waitCompleteResponse(unsigned long timeout, unsigned int waitNoAux) { |
||||
|
Status result = 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_TIMEOUT; |
||||
|
// DEBUG_PRINTLN(F("LORA: 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);
|
||||
|
this->managedDelay(3); |
||||
|
// 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_E32::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_E32::available(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;
|
||||
|
// }
|
||||
|
//
|
||||
|
// if (this->auxPin != 0) {
|
||||
|
// 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_E32::flush() { |
||||
|
this->serialDef.stream->flush(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void LoRa_E32::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_E32::sendStruct(void *structureManaged, uint16_t size_) { |
||||
|
if(size_ > MAX_SIZE_TX_PACKET){ |
||||
|
return ERR_PACKET_TOO_BIG; |
||||
|
} |
||||
|
|
||||
|
Status result = 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_NO_RESPONSE_FROM_DEVICE; |
||||
|
} else { |
||||
|
result = ERR_DATA_SIZE_NOT_MATCH; |
||||
|
} |
||||
|
} |
||||
|
if(result != SUCCESS) return result; |
||||
|
|
||||
|
result = this->waitCompleteResponse(1000); |
||||
|
if(result != 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_E32::receiveStruct(void *structureManaged, uint16_t size_) { |
||||
|
Status result = 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_NO_RESPONSE_FROM_DEVICE; |
||||
|
} else { |
||||
|
result = ERR_DATA_SIZE_NOT_MATCH; |
||||
|
} |
||||
|
} |
||||
|
if(result != SUCCESS) |
||||
|
return result; |
||||
|
|
||||
|
result = this->waitCompleteResponse(1000); |
||||
|
|
||||
|
if(result != SUCCESS) |
||||
|
return result; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* method to set the mode (program, normal, etc.) |
||||
|
*/ |
||||
|
Status LoRa_E32::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
|
||||
|
digitalWrite(this->m0Pin, LOW); |
||||
|
digitalWrite(this->m1Pin, LOW); |
||||
|
DEBUG_PRINTLN(F("MODE NORMAL!")); |
||||
|
break; |
||||
|
case MODE_1_WAKE_UP: |
||||
|
digitalWrite(this->m0Pin, HIGH); |
||||
|
digitalWrite(this->m1Pin, LOW); |
||||
|
DEBUG_PRINTLN(F("MODE WAKE UP!")); |
||||
|
break; |
||||
|
case MODE_2_POWER_SAVING: |
||||
|
digitalWrite(this->m0Pin, LOW); |
||||
|
digitalWrite(this->m1Pin, HIGH); |
||||
|
DEBUG_PRINTLN(F("MODE POWER SAVING!")); |
||||
|
break; |
||||
|
case MODE_3_SLEEP: |
||||
|
// Mode 3 | Setting operation
|
||||
|
digitalWrite(this->m0Pin, HIGH); |
||||
|
digitalWrite(this->m1Pin, HIGH); |
||||
|
DEBUG_PRINTLN(F("MODE PROGRAM/SLEEP!")); |
||||
|
break; |
||||
|
default: |
||||
|
return ERR_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 == SUCCESS){ |
||||
|
this->mode = mode; |
||||
|
} |
||||
|
|
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
MODE_TYPE LoRa_E32::getMode(){ |
||||
|
return this->mode; |
||||
|
} |
||||
|
|
||||
|
void LoRa_E32::writeProgramCommand(PROGRAM_COMMAND cmd){ |
||||
|
uint8_t CMD[3] = {cmd, cmd, cmd}; |
||||
|
uint8_t size = this->serialDef.stream->write(CMD, 3); |
||||
|
DEBUG_PRINTLN(size); |
||||
|
this->managedDelay(50); //need ti check
|
||||
|
} |
||||
|
|
||||
|
ResponseStructContainer LoRa_E32::getConfiguration(){ |
||||
|
ResponseStructContainer rc; |
||||
|
|
||||
|
rc.status.code = checkUARTConfiguration(MODE_3_PROGRAM); |
||||
|
if (rc.status.code!=SUCCESS) return rc; |
||||
|
|
||||
|
MODE_TYPE prevMode = this->mode; |
||||
|
|
||||
|
rc.status.code = this->setMode(MODE_3_PROGRAM); |
||||
|
if (rc.status.code!=SUCCESS) return rc; |
||||
|
|
||||
|
this->writeProgramCommand(READ_CONFIGURATION); |
||||
|
|
||||
|
rc.data = malloc(sizeof(Configuration)); |
||||
|
rc.status.code = this->receiveStruct((uint8_t *)rc.data, sizeof(Configuration)); |
||||
|
|
||||
|
#ifdef LoRa_E32_DEBUG
|
||||
|
this->printParameters((Configuration *)rc.data); |
||||
|
#endif
|
||||
|
|
||||
|
if (rc.status.code!=SUCCESS) { |
||||
|
this->setMode(prevMode); |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
DEBUG_PRINTLN("----------------------------------------"); |
||||
|
DEBUG_PRINT(F("HEAD BIN INSIDE: ")); DEBUG_PRINT(((Configuration *)rc.data)->HEAD, BIN);DEBUG_PRINT(" ");DEBUG_PRINT(((Configuration *)rc.data)->HEAD, DEC);DEBUG_PRINT(" ");DEBUG_PRINTLN(((Configuration *)rc.data)->HEAD, HEX); |
||||
|
DEBUG_PRINTLN("----------------------------------------"); |
||||
|
|
||||
|
rc.status.code = this->setMode(prevMode); |
||||
|
if (rc.status.code!=SUCCESS) return rc; |
||||
|
|
||||
|
// this->printParameters(*configuration);
|
||||
|
|
||||
|
if (0xC0 != ((Configuration *)rc.data)->HEAD && 0xC2 != ((Configuration *)rc.data)->HEAD){ |
||||
|
rc.status.code = ERR_HEAD_NOT_RECOGNIZED; |
||||
|
} |
||||
|
|
||||
|
// rc.data = configuration;
|
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
RESPONSE_STATUS LoRa_E32::checkUARTConfiguration(MODE_TYPE mode){ |
||||
|
if (mode==MODE_3_PROGRAM && this->bpsRate!=UART_BPS_RATE_9600){ |
||||
|
return ERR_WRONG_UART_CONFIG; |
||||
|
} |
||||
|
return SUCCESS; |
||||
|
} |
||||
|
|
||||
|
ResponseStatus LoRa_E32::setConfiguration(Configuration configuration, PROGRAM_COMMAND saveType){ |
||||
|
ResponseStatus rc; |
||||
|
|
||||
|
rc.code = checkUARTConfiguration(MODE_3_PROGRAM); |
||||
|
if (rc.code!=SUCCESS) return rc; |
||||
|
|
||||
|
MODE_TYPE prevMode = this->mode; |
||||
|
|
||||
|
rc.code = this->setMode(MODE_3_PROGRAM); |
||||
|
if (rc.code!=SUCCESS) return rc; |
||||
|
|
||||
|
this->writeProgramCommand(READ_CONFIGURATION); |
||||
|
|
||||
|
configuration.HEAD = saveType; |
||||
|
|
||||
|
rc.code = this->sendStruct((uint8_t *)&configuration, sizeof(Configuration)); |
||||
|
if (rc.code!=SUCCESS) { |
||||
|
this->setMode(prevMode); |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
DEBUG_PRINTLN("----------------------------------------"); |
||||
|
DEBUG_PRINT(F("HEAD BIN INSIDE: ")); DEBUG_PRINT(configuration.HEAD, BIN);DEBUG_PRINT(" ");DEBUG_PRINT(configuration.HEAD, DEC);DEBUG_PRINT(" ");DEBUG_PRINTLN(configuration.HEAD, HEX); |
||||
|
DEBUG_PRINTLN("----------------------------------------"); |
||||
|
|
||||
|
rc.code = this->setMode(prevMode); |
||||
|
if (rc.code!=SUCCESS) return rc; |
||||
|
|
||||
|
// this->printParameters(*configuration);
|
||||
|
|
||||
|
if (0xC0 != configuration.HEAD && 0xC2 != configuration.HEAD){ |
||||
|
rc.code = ERR_HEAD_NOT_RECOGNIZED; |
||||
|
} |
||||
|
|
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
ResponseStructContainer LoRa_E32::getModuleInformation(){ |
||||
|
ResponseStructContainer rc; |
||||
|
|
||||
|
rc.status.code = checkUARTConfiguration(MODE_3_PROGRAM); |
||||
|
if (rc.status.code!=SUCCESS) return rc; |
||||
|
|
||||
|
MODE_TYPE prevMode = this->mode; |
||||
|
|
||||
|
rc.status.code = this->setMode(MODE_3_PROGRAM); |
||||
|
if (rc.status.code!=SUCCESS) return rc; |
||||
|
|
||||
|
this->writeProgramCommand(READ_MODULE_VERSION); |
||||
|
|
||||
|
struct ModuleInformation *moduleInformation = (ModuleInformation *)malloc(sizeof(ModuleInformation)); |
||||
|
rc.status.code = this->receiveStruct((uint8_t *)moduleInformation, sizeof(ModuleInformation)); |
||||
|
if (rc.status.code!=SUCCESS) { |
||||
|
this->setMode(prevMode); |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
rc.status.code = this->setMode(prevMode); |
||||
|
if (rc.status.code!=SUCCESS) return rc; |
||||
|
|
||||
|
// this->printParameters(*configuration);
|
||||
|
|
||||
|
if (0xC3 != moduleInformation->HEAD){ |
||||
|
rc.status.code = ERR_HEAD_NOT_RECOGNIZED; |
||||
|
} |
||||
|
|
||||
|
DEBUG_PRINTLN("----------------------------------------"); |
||||
|
DEBUG_PRINT(F("HEAD BIN INSIDE: ")); DEBUG_PRINT(moduleInformation->HEAD, BIN);DEBUG_PRINT(" ");DEBUG_PRINT(moduleInformation->HEAD, DEC);DEBUG_PRINT(" ");DEBUG_PRINTLN(moduleInformation->HEAD, HEX); |
||||
|
|
||||
|
DEBUG_PRINT(F("Freq.: ")); DEBUG_PRINTLN(moduleInformation->frequency, HEX); |
||||
|
DEBUG_PRINT(F("Version : ")); DEBUG_PRINTLN(moduleInformation->version, HEX); |
||||
|
DEBUG_PRINT(F("Features : ")); DEBUG_PRINTLN(moduleInformation->features, HEX); |
||||
|
DEBUG_PRINTLN("----------------------------------------"); |
||||
|
|
||||
|
rc.data = moduleInformation; // malloc(sizeof (moduleInformation));
|
||||
|
|
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
ResponseStatus LoRa_E32::resetModule(){ |
||||
|
ResponseStatus status; |
||||
|
|
||||
|
status.code = checkUARTConfiguration(MODE_3_PROGRAM); |
||||
|
if (status.code!=SUCCESS) return status; |
||||
|
|
||||
|
MODE_TYPE prevMode = this->mode; |
||||
|
|
||||
|
status.code = this->setMode(MODE_3_PROGRAM); |
||||
|
if (status.code!=SUCCESS) return status; |
||||
|
|
||||
|
this->writeProgramCommand(WRITE_RESET_MODULE); |
||||
|
|
||||
|
status.code = this->waitCompleteResponse(1000); |
||||
|
if (status.code!=SUCCESS) { |
||||
|
this->setMode(prevMode); |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
status.code = this->setMode(prevMode); |
||||
|
if (status.code!=SUCCESS) return status; |
||||
|
|
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
ResponseContainer LoRa_E32::receiveMessage(){ |
||||
|
ResponseContainer rc; |
||||
|
rc.status.code = SUCCESS; |
||||
|
rc.data = this->serialDef.stream->readString(); |
||||
|
this->cleanUARTBuffer(); |
||||
|
if (rc.status.code!=SUCCESS) { |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
// rc.data = message; // malloc(sizeof (moduleInformation));
|
||||
|
|
||||
|
return rc; |
||||
|
} |
||||
|
ResponseContainer LoRa_E32::receiveMessageUntil(char delimiter){ |
||||
|
ResponseContainer rc; |
||||
|
rc.status.code = SUCCESS; |
||||
|
rc.data = this->serialDef.stream->readStringUntil(delimiter); |
||||
|
// this->cleanUARTBuffer();
|
||||
|
if (rc.status.code!=SUCCESS) { |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
// rc.data = message; // malloc(sizeof (moduleInformation));
|
||||
|
|
||||
|
return rc; |
||||
|
} |
||||
|
ResponseStructContainer LoRa_E32::receiveMessage(const uint8_t size){ |
||||
|
ResponseStructContainer rc; |
||||
|
|
||||
|
rc.data = malloc(size); |
||||
|
rc.status.code = this->receiveStruct((uint8_t *)rc.data, size); |
||||
|
this->cleanUARTBuffer(); |
||||
|
if (rc.status.code!=SUCCESS) { |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
ResponseStatus LoRa_E32::sendMessage(const void *message, const uint8_t size){ |
||||
|
ResponseStatus status; |
||||
|
status.code = this->sendStruct((uint8_t *)message, size); |
||||
|
if (status.code!=SUCCESS) return status; |
||||
|
|
||||
|
return status; |
||||
|
} |
||||
|
ResponseStatus LoRa_E32::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); |
||||
|
|
||||
|
ResponseStatus status; |
||||
|
status.code = this->sendStruct((uint8_t *)&messageFixed, size); |
||||
|
if (status.code!=SUCCESS) return status; |
||||
|
|
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
ResponseStatus LoRa_E32::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!=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_E32::sendBroadcastFixedMessage(byte CHAN, const String message){ |
||||
|
return this->sendFixedMessage(0xFF, 0xFF, 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_E32::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)
|
||||
|
|
||||
|
|
||||
|
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!=SUCCESS) return status;
|
||||
|
|
||||
|
return status; |
||||
|
} |
||||
|
ResponseStatus LoRa_E32::sendBroadcastFixedMessage(byte CHAN, const void *message, const uint8_t size){ |
||||
|
return this->sendFixedMessage(0xFF, 0xFF, CHAN, message, size); |
||||
|
} |
||||
|
|
||||
|
ResponseContainer LoRa_E32::receiveInitialMessage(uint8_t size){ |
||||
|
ResponseContainer rc; |
||||
|
rc.status.code = SUCCESS; |
||||
|
char buff[size]; |
||||
|
uint8_t len = this->serialDef.stream->readBytes(buff, size); |
||||
|
if (len!=size) { |
||||
|
if (len==0){ |
||||
|
rc.status.code = ERR_NO_RESPONSE_FROM_DEVICE; |
||||
|
}else{ |
||||
|
rc.status.code = ERR_DATA_SIZE_NOT_MATCH; |
||||
|
} |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
rc.data = buff; |
||||
|
|
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
#define KeeLoq_NLF 0x3A5C742E
|
||||
|
|
||||
|
unsigned long LoRa_E32::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_E32::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_E32_DEBUG
|
||||
|
void LoRa_E32::printParameters(struct Configuration *configuration) { |
||||
|
DEBUG_PRINTLN("----------------------------------------"); |
||||
|
|
||||
|
DEBUG_PRINT(F("HEAD : ")); DEBUG_PRINT(configuration->HEAD, BIN);DEBUG_PRINT(" ");DEBUG_PRINT(configuration->HEAD, DEC);DEBUG_PRINT(" ");DEBUG_PRINTLN(configuration->HEAD, HEX); |
||||
|
DEBUG_PRINTLN(F(" ")); |
||||
|
DEBUG_PRINT(F("AddH : ")); DEBUG_PRINTLN(configuration->ADDH, DEC); |
||||
|
DEBUG_PRINT(F("AddL : ")); DEBUG_PRINTLN(configuration->ADDL, DEC); |
||||
|
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.getUARTBaudRate()); |
||||
|
DEBUG_PRINT(F("SpeedAirDataRate : ")); DEBUG_PRINT(configuration->SPED.airDataRate, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->SPED.getAirDataRate()); |
||||
|
|
||||
|
DEBUG_PRINT(F("OptionTrans : ")); DEBUG_PRINT(configuration->OPTION.fixedTransmission, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->OPTION.getFixedTransmissionDescription()); |
||||
|
DEBUG_PRINT(F("OptionPullup : ")); DEBUG_PRINT(configuration->OPTION.ioDriveMode, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->OPTION.getIODroveModeDescription()); |
||||
|
DEBUG_PRINT(F("OptionWakeup : ")); DEBUG_PRINT(configuration->OPTION.wirelessWakeupTime, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->OPTION.getWirelessWakeUPTimeDescription()); |
||||
|
DEBUG_PRINT(F("OptionFEC : ")); DEBUG_PRINT(configuration->OPTION.fec, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->OPTION.getFECDescription()); |
||||
|
DEBUG_PRINT(F("OptionPower : ")); DEBUG_PRINT(configuration->OPTION.transmissionPower, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration->OPTION.getTransmissionPowerDescription()); |
||||
|
|
||||
|
DEBUG_PRINTLN("----------------------------------------"); |
||||
|
} |
||||
|
#endif
|
||||
@ -0,0 +1,298 @@ |
|||||
|
/* |
||||
|
* EBYTE LoRa E32 Series |
||||
|
*/ |
||||
|
#ifndef LoRa_E32_h |
||||
|
#define LoRa_E32_h |
||||
|
|
||||
|
#ifdef ESP32 |
||||
|
#define HARDWARE_SERIAL_SELECTABLE_PIN |
||||
|
#endif |
||||
|
|
||||
|
#ifdef ACTIVATE_SOFTWARE_SERIAL |
||||
|
#include <SoftwareSerial.h> |
||||
|
#endif |
||||
|
|
||||
|
#include "statesNaming.h" |
||||
|
|
||||
|
#if ARDUINO >= 100 |
||||
|
#include "Arduino.h" |
||||
|
#else |
||||
|
#include "WProgram.h" |
||||
|
#endif |
||||
|
|
||||
|
#define MAX_SIZE_TX_PACKET 58 |
||||
|
|
||||
|
// Uncomment to enable printing out nice debug messages. |
||||
|
// #define LoRa_E32_DEBUG |
||||
|
|
||||
|
// Operating Freq |
||||
|
#define FREQUENCY_915 |
||||
|
|
||||
|
// Define where debug output will be printed. |
||||
|
#define DEBUG_PRINTER Serial |
||||
|
|
||||
|
// Setup debug printing macros. |
||||
|
#ifdef LoRa_E32_DEBUG |
||||
|
#define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); } |
||||
|
#define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); } |
||||
|
#else |
||||
|
#define DEBUG_PRINT(...) {} |
||||
|
#define DEBUG_PRINTLN(...) {} |
||||
|
#endif |
||||
|
|
||||
|
enum MODE_TYPE |
||||
|
{ |
||||
|
MODE_0_NORMAL = 0, |
||||
|
MODE_1_WAKE_UP = 1, |
||||
|
MODE_2_POWER_SAVING = 2, |
||||
|
MODE_3_SLEEP = 3, |
||||
|
MODE_3_PROGRAM =3, |
||||
|
MODE_INIT = 0xFF |
||||
|
}; |
||||
|
|
||||
|
enum PROGRAM_COMMAND |
||||
|
{ |
||||
|
WRITE_CFG_PWR_DWN_SAVE = 0xC0, |
||||
|
READ_CONFIGURATION = 0xC1, |
||||
|
WRITE_CFG_PWR_DWN_LOSE = 0xC2, |
||||
|
READ_MODULE_VERSION = 0xC3, |
||||
|
WRITE_RESET_MODULE = 0xC4 |
||||
|
}; |
||||
|
|
||||
|
#pragma pack(push, 1) |
||||
|
struct Speed { |
||||
|
uint8_t airDataRate : 3; //bit 0-2 |
||||
|
String getAirDataRate() { |
||||
|
return getAirDataRateDescriptionByParams(this->airDataRate); |
||||
|
} |
||||
|
|
||||
|
uint8_t uartBaudRate: 3; //bit 3-5 |
||||
|
String getUARTBaudRate() { |
||||
|
return getUARTBaudRateDescriptionByParams(this->uartBaudRate); |
||||
|
} |
||||
|
|
||||
|
uint8_t uartParity: 2; //bit 6-7 |
||||
|
String getUARTParityDescription() { |
||||
|
return getUARTParityDescriptionByParams(this->uartParity); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct Option { |
||||
|
byte transmissionPower : 2; //bit 0-1 |
||||
|
String getTransmissionPowerDescription() { |
||||
|
return getTransmissionPowerDescriptionByParams(this->transmissionPower); |
||||
|
} |
||||
|
|
||||
|
byte fec : 1; //bit 2 |
||||
|
String getFECDescription() { |
||||
|
return getFECDescriptionByParams(this->fec); |
||||
|
} |
||||
|
|
||||
|
byte wirelessWakeupTime : 3; //bit 3-5 |
||||
|
String getWirelessWakeUPTimeDescription() { |
||||
|
return getWirelessWakeUPTimeDescriptionByParams(this->wirelessWakeupTime); |
||||
|
} |
||||
|
|
||||
|
byte ioDriveMode : 1; //bit 6 |
||||
|
String getIODroveModeDescription() { |
||||
|
return getIODriveModeDescriptionDescriptionByParams(this->ioDriveMode); |
||||
|
} |
||||
|
|
||||
|
byte fixedTransmission : 1; //bit 7 |
||||
|
String getFixedTransmissionDescription() { |
||||
|
return getFixedTransmissionDescriptionByParams(this->fixedTransmission); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
struct Configuration { |
||||
|
byte HEAD = 0; |
||||
|
byte ADDH = 0; |
||||
|
byte ADDL = 0; |
||||
|
struct Speed SPED; |
||||
|
byte CHAN = 0; |
||||
|
String getChannelDescription() { |
||||
|
return String(this->CHAN + OPERATING_FREQUENCY) + F("MHz") ; |
||||
|
} |
||||
|
struct Option OPTION; |
||||
|
}; |
||||
|
|
||||
|
struct ModuleInformation { |
||||
|
byte HEAD = 0; |
||||
|
byte frequency = 0; |
||||
|
byte version = 0; |
||||
|
byte features = 0; |
||||
|
}; |
||||
|
|
||||
|
struct ResponseStatus { |
||||
|
Status code; |
||||
|
String getResponseDescription() { |
||||
|
return getResponseDescriptionByParams(this->code); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct ResponseStructContainer { |
||||
|
void *data; |
||||
|
ResponseStatus status; |
||||
|
void close() { |
||||
|
free(this->data); |
||||
|
} |
||||
|
}; |
||||
|
struct ResponseContainer { |
||||
|
String data; |
||||
|
ResponseStatus status; |
||||
|
}; |
||||
|
//struct FixedStransmission { |
||||
|
// byte ADDL = 0; |
||||
|
// byte ADDH = 0; |
||||
|
// byte CHAN = 0; |
||||
|
// void *message; |
||||
|
//}; |
||||
|
#pragma pack(pop) |
||||
|
|
||||
|
class LoRa_E32 { |
||||
|
public: |
||||
|
LoRa_E32(HardwareSerial hs); |
||||
|
|
||||
|
/* |
||||
|
#ifdef ACTIVATE_SOFTWARE_SERIAL |
||||
|
LoRa_E32(byte txE32pin, byte rxE32pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
LoRa_E32(byte txE32pin, byte rxE32pin, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
LoRa_E32(byte txE32pin, byte rxE32pin, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
#endif |
||||
|
|
||||
|
LoRa_E32(HardwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
LoRa_E32(HardwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
LoRa_E32(HardwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
|
||||
|
#ifdef HARDWARE_SERIAL_SELECTABLE_PIN |
||||
|
LoRa_E32(byte txE32pin, byte rxE32pin, HardwareSerial* serial, UART_BPS_RATE bpsRate, uint32_t serialConfig = SERIAL_8N1); |
||||
|
LoRa_E32(byte txE32pin, byte rxE32pin, HardwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate, uint32_t serialConfig = SERIAL_8N1); |
||||
|
LoRa_E32(byte txE32pin, byte rxE32pin, HardwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate, uint32_t serialConfig = SERIAL_8N1); |
||||
|
#endif |
||||
|
|
||||
|
#ifdef ACTIVATE_SOFTWARE_SERIAL |
||||
|
LoRa_E32(SoftwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
LoRa_E32(SoftwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
LoRa_E32(SoftwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); |
||||
|
#endif |
||||
|
|
||||
|
// LoRa_E32(byte txE32pin, byte rxE32pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, MODE_TYPE mode = MODE_0_NORMAL); |
||||
|
// LoRa_E32(HardwareSerial* serial = &Serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, MODE_TYPE mode = MODE_0_NORMAL); |
||||
|
// LoRa_E32(SoftwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, MODE_TYPE mode = MODE_0_NORMAL); |
||||
|
*/ |
||||
|
bool begin(); |
||||
|
Status setMode(MODE_TYPE mode); |
||||
|
MODE_TYPE getMode(); |
||||
|
|
||||
|
ResponseStructContainer getConfiguration(); |
||||
|
ResponseStatus setConfiguration(Configuration configuration, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE); |
||||
|
|
||||
|
ResponseStructContainer getModuleInformation(); |
||||
|
ResponseStatus resetModule(); |
||||
|
|
||||
|
ResponseStatus sendMessage(const void *message, const uint8_t size); |
||||
|
ResponseStructContainer receiveMessage(const uint8_t size); |
||||
|
|
||||
|
ResponseStatus sendMessage(const String message); |
||||
|
ResponseContainer receiveMessage(); |
||||
|
|
||||
|
ResponseStatus sendFixedMessage(byte ADDH,byte ADDL, byte CHAN, const String message); |
||||
|
ResponseStatus sendBroadcastFixedMessage(byte CHAN, const String message); |
||||
|
|
||||
|
ResponseStatus sendFixedMessage(byte ADDH,byte ADDL, byte CHAN, const void *message, const uint8_t size); |
||||
|
ResponseStatus sendBroadcastFixedMessage(byte CHAN, const void *message, const uint8_t size ); |
||||
|
|
||||
|
ResponseContainer receiveInitialMessage(const uint8_t size); |
||||
|
ResponseContainer receiveMessageUntil(char delimiter = '\0'); |
||||
|
|
||||
|
int available(unsigned long timeout = 1000); |
||||
|
private: |
||||
|
HardwareSerial* hs; |
||||
|
|
||||
|
#ifdef ACTIVATE_SOFTWARE_SERIAL |
||||
|
SoftwareSerial* ss; |
||||
|
#endif |
||||
|
|
||||
|
bool isSoftwareSerial = true; |
||||
|
|
||||
|
int8_t txE32pin = -1; |
||||
|
int8_t rxE32pin = -1; |
||||
|
int8_t auxPin = -1; |
||||
|
|
||||
|
#ifdef HARDWARE_SERIAL_SELECTABLE_PIN |
||||
|
uint32_t serialConfig = SERIAL_8N1; |
||||
|
#endif |
||||
|
|
||||
|
int8_t m0Pin = -1; |
||||
|
int8_t m1Pin = -1; |
||||
|
|
||||
|
unsigned long halfKeyloqKey = 0x06660708; |
||||
|
unsigned long encrypt(unsigned long data); |
||||
|
unsigned long decrypt(unsigned long data); |
||||
|
|
||||
|
UART_BPS_RATE bpsRate = UART_BPS_RATE_9600; |
||||
|
|
||||
|
struct NeedsStream{ |
||||
|
template< typename T > |
||||
|
void begin( T &t, int baud){ |
||||
|
DEBUG_PRINTLN("Begin "); |
||||
|
t.setTimeout(500); |
||||
|
t.begin(baud); |
||||
|
stream = &t; |
||||
|
} |
||||
|
|
||||
|
#ifdef HARDWARE_SERIAL_SELECTABLE_PIN |
||||
|
// template< typename T > |
||||
|
// void begin( T &t, int baud, SerialConfig config ){ |
||||
|
// DEBUG_PRINTLN("Begin "); |
||||
|
// t.setTimeout(500); |
||||
|
// t.begin(baud, config); |
||||
|
// stream = &t; |
||||
|
// } |
||||
|
// |
||||
|
template< typename T > |
||||
|
void begin( T &t, int baud, uint32_t config ){ |
||||
|
DEBUG_PRINTLN("Begin "); |
||||
|
t.setTimeout(500); |
||||
|
t.begin(baud, config); |
||||
|
stream = &t; |
||||
|
} |
||||
|
|
||||
|
template< typename T > |
||||
|
void begin( T &t, int baud, uint32_t config, int8_t txE32pin, int8_t rxE32pin ){ |
||||
|
DEBUG_PRINTLN("Begin "); |
||||
|
t.setTimeout(500); |
||||
|
t.begin(baud, config, txE32pin, rxE32pin); |
||||
|
stream = &t; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
void listen(){ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
Stream *stream; |
||||
|
}; |
||||
|
NeedsStream serialDef; |
||||
|
|
||||
|
MODE_TYPE mode = MODE_0_NORMAL; |
||||
|
|
||||
|
void managedDelay(unsigned long timeout); |
||||
|
Status waitCompleteResponse(unsigned long timeout = 1000, unsigned int waitNoAux = 100); |
||||
|
void flush(); |
||||
|
void cleanUARTBuffer(); |
||||
|
|
||||
|
Status sendStruct(void *structureManaged, uint16_t size_); |
||||
|
Status receiveStruct(void *structureManaged, uint16_t size_); |
||||
|
void writeProgramCommand(PROGRAM_COMMAND cmd); |
||||
|
|
||||
|
RESPONSE_STATUS checkUARTConfiguration(MODE_TYPE mode); |
||||
|
|
||||
|
#ifdef LoRa_E32_DEBUG |
||||
|
void printParameters(struct Configuration *configuration); |
||||
|
#endif |
||||
|
}; |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,452 @@ |
|||||
|
#include "Arduino.h" |
||||
|
|
||||
|
#define FREQUENCY_915 |
||||
|
|
||||
|
#ifdef FREQUENCY_433 |
||||
|
#define OPERATING_FREQUENCY 410 |
||||
|
#elif defined(FREQUENCY_170) |
||||
|
#define OPERATING_FREQUENCY 130 |
||||
|
#elif defined(FREQUENCY_470) |
||||
|
#define OPERATING_FREQUENCY 370 |
||||
|
#elif defined(FREQUENCY_868) |
||||
|
#define OPERATING_FREQUENCY 862 |
||||
|
#elif defined(FREQUENCY_915) |
||||
|
#define OPERATING_FREQUENCY 900 |
||||
|
#else |
||||
|
#define OPERATING_FREQUENCY 410 |
||||
|
#endif |
||||
|
|
||||
|
#define BROADCAST_ADDRESS 0xFF |
||||
|
|
||||
|
typedef enum RESPONSE_STATUS { |
||||
|
SUCCESS = 1, |
||||
|
ERR_UNKNOWN, /* something shouldn't happened */ |
||||
|
ERR_NOT_SUPPORT, |
||||
|
ERR_NOT_IMPLEMENT, |
||||
|
ERR_NOT_INITIAL, |
||||
|
ERR_INVALID_PARAM, |
||||
|
ERR_DATA_SIZE_NOT_MATCH, |
||||
|
ERR_BUF_TOO_SMALL, |
||||
|
ERR_TIMEOUT, |
||||
|
ERR_HARDWARE, |
||||
|
ERR_HEAD_NOT_RECOGNIZED, |
||||
|
ERR_NO_RESPONSE_FROM_DEVICE, |
||||
|
ERR_WRONG_UART_CONFIG, |
||||
|
ERR_PACKET_TOO_BIG |
||||
|
} Status; |
||||
|
|
||||
|
static String getResponseDescriptionByParams(byte status){ |
||||
|
switch (status) |
||||
|
{ |
||||
|
case SUCCESS: |
||||
|
return F("Success"); |
||||
|
break; |
||||
|
case ERR_UNKNOWN: |
||||
|
return F("Unknown"); |
||||
|
break; |
||||
|
case ERR_NOT_SUPPORT: |
||||
|
return F("Not support!"); |
||||
|
break; |
||||
|
case ERR_NOT_IMPLEMENT: |
||||
|
return F("Not implement"); |
||||
|
break; |
||||
|
case ERR_NOT_INITIAL: |
||||
|
return F("Not initial!"); |
||||
|
break; |
||||
|
case ERR_INVALID_PARAM: |
||||
|
return F("Invalid param!"); |
||||
|
break; |
||||
|
case ERR_DATA_SIZE_NOT_MATCH: |
||||
|
return F("Data size not match!"); |
||||
|
break; |
||||
|
case ERR_BUF_TOO_SMALL: |
||||
|
return F("Buff too small!"); |
||||
|
break; |
||||
|
case ERR_TIMEOUT: |
||||
|
return F("Timeout!!"); |
||||
|
break; |
||||
|
case ERR_HARDWARE: |
||||
|
return F("Hardware error!"); |
||||
|
break; |
||||
|
case ERR_HEAD_NOT_RECOGNIZED: |
||||
|
return F("Save mode returned not recognized!"); |
||||
|
break; |
||||
|
case ERR_NO_RESPONSE_FROM_DEVICE: |
||||
|
return F("No response from device! (Check wiring)"); |
||||
|
break; |
||||
|
case ERR_WRONG_UART_CONFIG: |
||||
|
return F("Wrong UART configuration! (BPS must be 9600 for configuration)"); |
||||
|
break; |
||||
|
case ERR_PACKET_TOO_BIG: |
||||
|
return F("The device support only 58byte of data transmission!"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid status!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
enum UART_PARITY |
||||
|
{ |
||||
|
MODE_00_8N1 = B00, |
||||
|
MODE_01_8O1 = B01, |
||||
|
MODE_10_8E1 = B10, |
||||
|
MODE_11_8N1 = B11 |
||||
|
}; |
||||
|
|
||||
|
static String getUARTParityDescriptionByParams(byte uartParity){ |
||||
|
switch (uartParity) |
||||
|
{ |
||||
|
case MODE_00_8N1: |
||||
|
return F("8N1 (Default)"); |
||||
|
break; |
||||
|
case MODE_01_8O1: |
||||
|
return F("8O1"); |
||||
|
break; |
||||
|
case MODE_10_8E1: |
||||
|
return F("8E1"); |
||||
|
break; |
||||
|
case MODE_11_8N1: |
||||
|
return F("8N1"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid UART Parity!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
enum UART_BPS_TYPE |
||||
|
{ |
||||
|
UART_BPS_1200 = B000, |
||||
|
UART_BPS_2400 = B001, |
||||
|
UART_BPS_4800 = B010, |
||||
|
UART_BPS_9600 = B011, |
||||
|
UART_BPS_19200 = B100, |
||||
|
UART_BPS_38400 = B101, |
||||
|
UART_BPS_57600 = B110, |
||||
|
UART_BPS_115200 = B111 |
||||
|
}; |
||||
|
|
||||
|
enum UART_BPS_RATE |
||||
|
{ |
||||
|
UART_BPS_RATE_1200 = 1200, |
||||
|
UART_BPS_RATE_2400 = 2400, |
||||
|
UART_BPS_RATE_4800 = 4800, |
||||
|
UART_BPS_RATE_9600 = 9600, |
||||
|
UART_BPS_RATE_19200 = 19200, |
||||
|
UART_BPS_RATE_38400 = 38400, |
||||
|
UART_BPS_RATE_57600 = 57600, |
||||
|
UART_BPS_RATE_115200 = 115200 |
||||
|
}; |
||||
|
|
||||
|
static String getUARTBaudRateDescriptionByParams(byte uartBaudRate) |
||||
|
{ |
||||
|
switch (uartBaudRate) |
||||
|
{ |
||||
|
case UART_BPS_1200: |
||||
|
return F("1200bps"); |
||||
|
break; |
||||
|
case UART_BPS_2400: |
||||
|
return F("2400bps"); |
||||
|
break; |
||||
|
case UART_BPS_4800: |
||||
|
return F("4800bps"); |
||||
|
break; |
||||
|
case UART_BPS_9600: |
||||
|
return F("9600bps (default)"); |
||||
|
break; |
||||
|
case UART_BPS_19200: |
||||
|
return F("19200bps"); |
||||
|
break; |
||||
|
case UART_BPS_38400: |
||||
|
return F("38400bps"); |
||||
|
break; |
||||
|
case UART_BPS_57600: |
||||
|
return F("57600bps"); |
||||
|
break; |
||||
|
case UART_BPS_115200: |
||||
|
return F("115200bps"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid UART Baud Rate!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
enum AIR_DATA_RATE |
||||
|
{ |
||||
|
AIR_DATA_RATE_000_03 = B000, |
||||
|
AIR_DATA_RATE_001_12 = B001, |
||||
|
AIR_DATA_RATE_010_24 = B010, |
||||
|
AIR_DATA_RATE_011_48 = B011, |
||||
|
AIR_DATA_RATE_100_96 = B100, |
||||
|
AIR_DATA_RATE_101_192 = B101, |
||||
|
AIR_DATA_RATE_110_192 = B110, |
||||
|
AIR_DATA_RATE_111_192 = B111 |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
static String getAirDataRateDescriptionByParams(byte airDataRate) |
||||
|
{ |
||||
|
switch (airDataRate) |
||||
|
{ |
||||
|
case AIR_DATA_RATE_000_03: |
||||
|
return F("0.3kbps"); |
||||
|
break; |
||||
|
case AIR_DATA_RATE_001_12: |
||||
|
return F("1.2kbps"); |
||||
|
break; |
||||
|
case AIR_DATA_RATE_010_24: |
||||
|
return F("2.4kbps (default)"); |
||||
|
break; |
||||
|
case AIR_DATA_RATE_011_48: |
||||
|
return F("4.8kbps"); |
||||
|
break; |
||||
|
case AIR_DATA_RATE_100_96: |
||||
|
return F("9.6kbps"); |
||||
|
break; |
||||
|
case AIR_DATA_RATE_101_192: |
||||
|
return F("19.2kbps"); |
||||
|
break; |
||||
|
case AIR_DATA_RATE_110_192: |
||||
|
return F("19.2kbps"); |
||||
|
break; |
||||
|
case AIR_DATA_RATE_111_192: |
||||
|
return F("19.2kbps"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid Air Data Rate!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
enum FIDEX_TRANSMISSION |
||||
|
{ |
||||
|
FT_TRANSPARENT_TRANSMISSION = B0, |
||||
|
FT_FIXED_TRANSMISSION = B1 |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
static String getFixedTransmissionDescriptionByParams(byte fixedTransmission) |
||||
|
{ |
||||
|
switch (fixedTransmission) |
||||
|
{ |
||||
|
case FT_TRANSPARENT_TRANSMISSION: |
||||
|
return F("Transparent transmission (default)"); |
||||
|
break; |
||||
|
case FT_FIXED_TRANSMISSION: |
||||
|
return F("Fixed transmission (first three bytes can be used as high/low address and channel)"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid fixed transmission param!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
enum IO_DRIVE_MODE |
||||
|
{ |
||||
|
IO_D_MODE_OPEN_COLLECTOR = B0, |
||||
|
IO_D_MODE_PUSH_PULLS_PULL_UPS = B1 |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
static String getIODriveModeDescriptionDescriptionByParams(byte ioDriveMode) |
||||
|
{ |
||||
|
switch (ioDriveMode) |
||||
|
{ |
||||
|
case IO_D_MODE_OPEN_COLLECTOR: |
||||
|
return F("TXD, RXD, AUX are open-collectors"); |
||||
|
break; |
||||
|
case IO_D_MODE_PUSH_PULLS_PULL_UPS: |
||||
|
return F("TXD, RXD, AUX are push-pulls/pull-ups"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid IO drive mode!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
enum WIRELESS_WAKE_UP_TIME |
||||
|
{ |
||||
|
WAKE_UP_250 = B000, |
||||
|
WAKE_UP_500 = B001, |
||||
|
WAKE_UP_750 = B010, |
||||
|
WAKE_UP_1000 = B011, |
||||
|
WAKE_UP_1250 = B100, |
||||
|
WAKE_UP_1500 = B101, |
||||
|
WAKE_UP_1750 = B110, |
||||
|
WAKE_UP_2000 = B111 |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
static String getWirelessWakeUPTimeDescriptionByParams(byte wirelessWakeUPTime) |
||||
|
{ |
||||
|
switch (wirelessWakeUPTime) |
||||
|
{ |
||||
|
case WAKE_UP_250: |
||||
|
return F("250ms (default)"); |
||||
|
break; |
||||
|
case WAKE_UP_500: |
||||
|
return F("500ms"); |
||||
|
break; |
||||
|
case WAKE_UP_750: |
||||
|
return F("750ms"); |
||||
|
break; |
||||
|
case WAKE_UP_1000: |
||||
|
return F("1000ms"); |
||||
|
break; |
||||
|
case WAKE_UP_1250: |
||||
|
return F("1250ms"); |
||||
|
break; |
||||
|
case WAKE_UP_1500: |
||||
|
return F("1500ms"); |
||||
|
break; |
||||
|
case WAKE_UP_1750: |
||||
|
return F("1750ms"); |
||||
|
break; |
||||
|
case WAKE_UP_2000: |
||||
|
return F("2000ms"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid wireless wake-up mode!"); |
||||
|
} |
||||
|
} |
||||
|
enum FORWARD_ERROR_CORRECTION_SWITCH |
||||
|
{ |
||||
|
FEC_0_OFF = B0, |
||||
|
FEC_1_ON = B1 |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
static String getFECDescriptionByParams(byte fec) |
||||
|
{ |
||||
|
switch (fec) |
||||
|
{ |
||||
|
case FEC_0_OFF: |
||||
|
return F("Turn off Forward Error Correction Switch"); |
||||
|
break; |
||||
|
case FEC_1_ON: |
||||
|
return F("Turn on Forward Error Correction Switch (Default)"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid FEC param"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#ifdef E32_TTL_100 |
||||
|
enum TRANSMISSION_POWER |
||||
|
{ |
||||
|
POWER_20 = B00, |
||||
|
POWER_17 = B01, |
||||
|
POWER_14 = B10, |
||||
|
POWER_10 = B11 |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
static String getTransmissionPowerDescriptionByParams(byte transmissionPower) |
||||
|
{ |
||||
|
switch (transmissionPower) |
||||
|
{ |
||||
|
case POWER_20: |
||||
|
return F("20dBm (Default)"); |
||||
|
break; |
||||
|
case POWER_17: |
||||
|
return F("17dBm"); |
||||
|
break; |
||||
|
case POWER_14: |
||||
|
return F("14dBm"); |
||||
|
break; |
||||
|
case POWER_10: |
||||
|
return F("10dBm"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid transmission power param"); |
||||
|
} |
||||
|
} |
||||
|
#elif defined(E32_TTL_500) |
||||
|
enum TRANSMISSION_POWER |
||||
|
{ |
||||
|
POWER_27 = B00, |
||||
|
POWER_24 = B01, |
||||
|
POWER_21 = B10, |
||||
|
POWER_18 = B11 |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
static String getTransmissionPowerDescriptionByParams(byte transmissionPower) |
||||
|
{ |
||||
|
switch (transmissionPower) |
||||
|
{ |
||||
|
case POWER_27: |
||||
|
return F("27dBm (Default)"); |
||||
|
break; |
||||
|
case POWER_24: |
||||
|
return F("24dBm"); |
||||
|
break; |
||||
|
case POWER_21: |
||||
|
return F("21dBm"); |
||||
|
break; |
||||
|
case POWER_18: |
||||
|
return F("18dBm"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid transmission power param"); |
||||
|
} |
||||
|
} |
||||
|
#elif defined(E32_TTL_1W) |
||||
|
enum TRANSMISSION_POWER |
||||
|
{ |
||||
|
POWER_30 = B00, |
||||
|
POWER_27 = B01, |
||||
|
POWER_24 = B10, |
||||
|
POWER_21 = B11 |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
static String getTransmissionPowerDescriptionByParams(byte transmissionPower) |
||||
|
{ |
||||
|
switch (transmissionPower) |
||||
|
{ |
||||
|
case POWER_30: |
||||
|
return F("30dBm (Default)"); |
||||
|
break; |
||||
|
case POWER_27: |
||||
|
return F("27dBm"); |
||||
|
break; |
||||
|
case POWER_24: |
||||
|
return F("24dBm"); |
||||
|
break; |
||||
|
case POWER_21: |
||||
|
return F("21dBm"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid transmission power param"); |
||||
|
} |
||||
|
} |
||||
|
#else |
||||
|
enum TRANSMISSION_POWER |
||||
|
{ |
||||
|
POWER_20 = B00, |
||||
|
POWER_17 = B01, |
||||
|
POWER_14 = B10, |
||||
|
POWER_10 = B11 |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
static String getTransmissionPowerDescriptionByParams(byte transmissionPower) |
||||
|
{ |
||||
|
switch (transmissionPower) |
||||
|
{ |
||||
|
case POWER_20: |
||||
|
return F("20dBm (Default)"); |
||||
|
break; |
||||
|
case POWER_17: |
||||
|
return F("17dBm"); |
||||
|
break; |
||||
|
case POWER_14: |
||||
|
return F("14dBm"); |
||||
|
break; |
||||
|
case POWER_10: |
||||
|
return F("10dBm"); |
||||
|
break; |
||||
|
default: |
||||
|
return F("Invalid transmission power param"); |
||||
|
} |
||||
|
} |
||||
|
#endif |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue