diff --git a/main/lorawan.h b/main/lorawan.h index b19e59c..226eb7a 100644 --- a/main/lorawan.h +++ b/main/lorawan.h @@ -23,8 +23,8 @@ class LoRaWANnode uint32_t JoinNonce; // from Join-Accept: unique must not be reused uint32_t HomeNetID; // from Join-Accept: Home Network ID uint32_t DevAddr; // from Join-Accept: Device Address - uint8_t DLsetting; // from Join-Accept: DownLink configuration: OptNeg | RX1DRoffset | RX2 data rate - uint8_t RxDelay; // from Join-Accept: + uint8_t DLsetting; // from Join-Accept: DownLink configuration: OptNeg:1 | RX1 data rate offset:3 | RX2 data rate:4 + uint8_t RxDelay; // from Join-Accept: RFU:4 | Del:4 Del=1..15s for the RX1, RX2 delay is Del+1 uint8_t State; // 0:disconencted, 1:join-request sent, 2:join-accept received, 3:uplink-packet sent uint8_t Chan; // [0..7] Current channel being used uint32_t UpCount; // [seq] Uplink frame counter: reset when joining the network @@ -175,24 +175,26 @@ class LoRaWANnode { int Len=getDataPacket(Packet, Data, DataLen, Port, Confirm); *Pkt = Packet; return Len; } int procRxData(const RFM_LoRa_RxPacket &RxPacket) - { int Ret=procRxData(RxPacket.Byte, RxPacket.Len); if(Ret<0) return Ret; - RxSNR += (RxPacket.SNR-RxSNR+1)/2; + { int Ret = procRxData(RxPacket.Byte, RxPacket.Len); if(Ret<0) return Ret; + RxSNR += (RxPacket.SNR-RxSNR+1)/2; // if good packet then update the signal statistics RxRSSI += (RxPacket.RSSI-RxRSSI+1)/2; return Ret; } int procRxData(const uint8_t *PktData, int PktLen) { if(PktLen<12) return -1; - uint8_t Type = PktData[0]>>5; if(Type!=3 && Type!=5) return -1; - uint32_t Addr=readInt(PktData+1, 4); - if(Addr!=DevAddr) return 0; - uint8_t Ctrl = PktData[5]; // Frame control: ADR | RFU | ACK | FPending | FOptLen[4] - uint32_t Count=readInt(PktData+6, 2); - int16_t CountDiff = Count-DnCount; // - if(CountDiff<=0) return -1; // attempt to reuse the counter: drop this packet + uint8_t Type = PktData[0]>>5; if(Type!=3 && Type!=5) return -1; // Frame Type: 3=unconfirmed data downlink, 5=confirmed data downlink + uint32_t Addr=readInt(PktData+1, 4); // device address + if(Addr!=DevAddr) return 0; // check if packet is for us (it could be for somebody else) + uint8_t Ctrl = PktData[5]; // Frame Control: ADR | RFU | ACK | FPending | FOptLen[4] + uint32_t Count = readInt(PktData+6, 2); // download counter + int16_t CountDiff = Count-DnCount; // how many we have missed ? + if(CountDiff<=0) return -1; // attempt to reuse the counter: drop this packet uint32_t MIC=0; LoRaMacComputeMic(PktData, PktLen-4, NetSesKey, Addr, 0x01, Count, &MIC); if(memcmp(PktData+PktLen-4, &MIC, 4)) return -1; // give up if MIC does not match - uint8_t DataOfs = 8 + (Ctrl&0x0F); // where the port byte should be + uint8_t OptLen = Ctrl&0x0F; // Options: how many bytes + uint8_t DataOfs = 8 + OptLen; // where the port byte should be + if(OptLen) procRxOpt(PktData+8, OptLen); // process the options (these are not encrypted) uint8_t DataLen = PktLen-DataOfs-4; // number of bytes of the user data field if(DataLen) // if non-zero { Packet[0] = PktData[DataOfs]; // copy port number @@ -208,8 +210,20 @@ class LoRaWANnode if(Type==5) TxACK=1; // if ACK requested RxPend = Ctrl&0x10; // is there more data pending to be received on next round ? State=2; + // if(DataLen==0) + // { Packet[0]=0x00; DataLen++; // copy MAC commands to user buffer for debug + // for(uint8_t Idx=0; Idx0; Wait--) { vTaskDelay(1); if(TRX.readIRQ()) break; } // IRQ signals packet reception - if(Wait) + if(Wait) // if no timeout thus a packet has been received. { TRX.LoRa_ReceivePacket(WAN_RxPacket); xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_UnsDec(CONS_UART_Write, xTaskGetTickCount(), 4, 3); @@ -442,42 +443,42 @@ extern "C" Format_UnsDec(CONS_UART_Write, (unsigned)Wait); Format_String(CONS_UART_Write, "ms\n"); xSemaphoreGive(CONS_Mutex); - if(WANdev.State==1) WANdev.procJoinAccept(WAN_RxPacket); // if join-request state then expect a join-accept packet + if(WANdev.State==1) WANdev.procJoinAccept(WAN_RxPacket); // if join-request state then expect a join-accept packet else if(WANdev.State==3) RxLen=WANdev.procRxData(WAN_RxPacket); // if data send then respect ACK and/or downlink data packet } - else WANdev.State--; - TRX.setFSK(); // back to FSK - SetFreqPlanOGN(); // OGN frequency plan - TRX.OGN_Configure(0, OGN_SYNC); // OGN config + else WANdev.State--; // if no packet received then retreat the State + TRX.setFSK(); // back to FSK + SetFreqPlanOGN(); // OGN frequency plan + TRX.OGN_Configure(0, OGN_SYNC); // OGN config SetRxChannel(); - TRX.setModeRX(); // switch to receive mode + TRX.setModeRX(); // switch to receive mode TRX.ClearIrqFlags(); - WANdev.WriteToNVS(); // store new WAN state in flash - if(RxLen>0) // if Downlink data received + WANdev.WriteToNVS(); // store new WAN state in flash + if(RxLen>0) // if Downlink data received { xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "LoRaWAN Msg: "); // Format_UnsDec(CONS_UART_Write, (uint16_t)RxLen); // Format_String(CONS_UART_Write, "B"); for(int Idx=0; Idx>16)&0xF)==0x8 ); } else { TxPktLen=WANdev.getDataPacket(&TxPacket, PktData, 20, 1, ((RX_Random>>16)&0xF)==0x8 ); } - TRX.LoRa_SendPacket(TxPacket, TxPktLen); RespDelay=1000; + TRX.LoRa_SendPacket(TxPacket, TxPktLen); RespDelay = WANdev.RxDelay&0x0F; if(RespDelay<1) RespDelay=1; RespDelay*=1000; WAN_BackOff=50+(RX_Random%21); XorShift32(RX_Random); } } if(RespDelay) @@ -706,7 +707,7 @@ extern "C" { vTaskDelay(1); if(!TRX.isModeLoRaTX()) break; } // uint8_t Mode=TRX.ReadMode(); // if(Mode!=RF_OPMODE_LORA_TX) break; } - WAN_RespTick=xTaskGetTickCount()+RespDelay; // when to expect the response: 5sec after the end of Join-Request packet + WAN_RespTick=xTaskGetTickCount()+RespDelay; // when to expect the response after the end of transmitted packet xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_UnsDec(CONS_UART_Write, xTaskGetTickCount(), 4, 3); Format_String(CONS_UART_Write, "s LoRaWAN Tx: "); diff --git a/main/rfm.h b/main/rfm.h index 581fde7..e07e052 100644 --- a/main/rfm.h +++ b/main/rfm.h @@ -243,12 +243,12 @@ SX1262 setup calls #ifdef WITH_SX1262 #include "sx1262.h" -#define RF_IRQ_PacketSent 0x0001 // packet transmission was completed -#define RF_IRQ_PayloadReady 0x0002 // -#define RF_IRQ_PreambleDetect 0x0004 // -#define RF_IRQ_SyncAddrMatch 0x0008 // -#define RF_IRQ_CrcErr 0x0040 // -#define RF_IRQ_Timeout 0x0200 // +// #define RF_IRQ_PacketSent 0x0001 // packet transmission was completed +// #define RF_IRQ_PayloadReady 0x0002 // +// #define RF_IRQ_PreambleDetect 0x0004 // +// #define RF_IRQ_SyncAddrMatch 0x0008 // +// #define RF_IRQ_CrcErr 0x0040 // +// #define RF_IRQ_Timeout 0x0200 // #endif @@ -738,7 +738,6 @@ class RFM_TRX void LoRa_Configure(RFM_LoRa_Config CFG, uint8_t MaxSize=64) { setChannel(0); - setDioMode(IRQ_TXDONE | IRQ_RXDONE); uint8_t Param[8]; Param[0] = CFG.SF; // Spreading Factor Param[1] = CFG.BW-3; // work only for 62.5/125/256/512kHz @@ -752,13 +751,13 @@ class RFM_TRX Param[4] = CFG.CRC; // check or not CRC Param[5] = CFG.InvIQ; // common flag for Tx/Rx Cmd_Write(CMD_SETPACKETPARAMS, Param, 6); // 0x8C, PacketParam + setDioMode( /* IRQ_TXDONE | */ IRQ_RXDONE); Param[0] = (CFG.SYNC&0xF0) | 0x04; Param[1] = (CFG.SYNC<<4) | 0x04; Regs_Write(REG_LORASYNCWORD, Param, 2); } void OGN_Configure(int16_t Channel, const uint8_t *SyncData) { setChannel(Channel); - setDioMode(IRQ_TXDONE | IRQ_RXDONE); uint8_t Param[12]; Pack3bytes(Param, 10240); // data bitrate = 32*Xtal/100e3 for OGN 100kbps Param[3] = 0x09; // 0x00:no filter, 0x08:BT=0.3, 0x09:BT=0.5, 0x0A:BT=0.7, 0x0B:BT=1.0 @@ -775,11 +774,11 @@ class RFM_TRX Param[7] = 0x01; // no CRC Param[8] = 0x00; // no whitening Cmd_Write(CMD_SETPACKETPARAMS, Param, 9); // 0x8C, PacketParam + setDioMode(/* IRQ_TXDONE | */ IRQ_RXDONE); Regs_Write(REG_SYNCWORD0, SyncData, 8); } // Write the SYNC word void PAW_Configure(const uint8_t *Sync) { setFrequency(869525000); - setDioMode(IRQ_TXDONE | IRQ_RXDONE); uint8_t Param[12]; Pack3bytes(Param, 26667); // data bitrate = 32*Xtal/38.4e3 for PAW 38.4kbps Param[3] = 0x09; // 0x00:no filter, 0x08:BT=0.3, 0x09:BT=0.5, 0x0A:BT=0.7, 0x0B:BT=1.0 @@ -796,6 +795,7 @@ class RFM_TRX Param[7] = 0x01; // no CRC Param[8] = 0x00; // no whitening Cmd_Write(CMD_SETPACKETPARAMS, Param, 9); // 0x8C, PacketParam + setDioMode( /* IRQ_TXDONE | */ IRQ_RXDONE); Regs_Write(REG_SYNCWORD0, Sync, 8); } // Write the SYNC word void ClearIrqFlags(uint16_t Mask=IRQ_ALL) { uint8_t Data[2]; Data[0]=Mask>>8; Data[1]=Mask; Cmd_Write(CMD_CLEARIRQSTATUS, Data, 2); }