diff --git a/Firmware/LoRaSerial/Commands.ino b/Firmware/LoRaSerial/Commands.ino index 596104f6..80495997 100644 --- a/Firmware/LoRaSerial/Commands.ino +++ b/Firmware/LoRaSerial/Commands.ino @@ -226,11 +226,15 @@ bool commandAT(const char * commandString) systemPrintln(" ATI10 - Display radio metrics"); systemPrintln(" ATI11 - Display the system runtime"); systemPrintln(" ATI12 - Set programming complete"); + systemPrintln(" ATI13 - Display the random seed"); + systemPrintln(" ATI14 - Display the channel table by channel"); + systemPrintln(" ATI15 - Display the channel table by frequency"); //Virtual circuit information commands systemPrintln(" ATI30 - Return myVc value"); systemPrintln(" ATI31 - Display the VC details"); systemPrintln(" ATI32 - Dump the NVM unique ID table"); + systemPrintln(" ATI33 - Display the VC states"); return true; case ('0'): //ATI0 - Show user settable parameters @@ -637,6 +641,69 @@ bool commandAT(const char * commandString) systemWrite(*data++); } return true; + + case ('3'): //ATI13 - Display the random seed + systemPrint("myRandSeed: "); + systemPrintln(myRandSeed); + return true; + + case ('4'): //ATI14 - Display the channel table by channel + systemPrintln("Channel Table"); + if (!channels) + systemPrintln(" Channel table not allocated!"); + else + { + for (int index = 0; index < settings.numberOfChannels; index++) + { + systemPrint(" Channel "); + if ((index <= 9) && (settings.numberOfChannels >= 10)) + systemPrint(" "); + systemPrint(index); + systemPrint(": "); + systemPrint(channels[index],3); + systemPrintln(" MHz"); + } + } + return true; + + case ('5'): //ATI14 - Display the channel table by frequency + systemPrintln("Channel Table by Frequency"); + if (!channels) + systemPrintln(" Channel table not allocated!"); + else + { + //Initialize the channel array + uint8_t chanIndex[settings.numberOfChannels]; + for (int index = 0; index < settings.numberOfChannels; index++) + chanIndex[index] = index; + + //Sort the channel numbers by frequency + for (int index = 0; index < (settings.numberOfChannels - 1); index++) + { + for (int x = index + 1; x < settings.numberOfChannels; x++) + { + if (channels[chanIndex[index]] > channels[chanIndex[x]]) + { + uint8_t f = chanIndex[index]; + chanIndex[index] = chanIndex[x]; + chanIndex[x] = f; + } + } + } + + //Display the frequencies + for (int index = 0; index < settings.numberOfChannels; index++) + { + systemPrint(" Channel "); + if ((chanIndex[index] <= 9) && (settings.numberOfChannels >= 10)) + systemPrint(" "); + systemPrint(chanIndex[index]); + systemPrint(": "); + systemPrint(channels[chanIndex[index]],3); + systemPrintln(" MHz"); + } + } + return true; } } if ((commandString[2] == 'I') && (commandString[3] == '3') && (commandLength == 5)) @@ -769,6 +836,17 @@ bool commandAT(const char * commandString) systemPrintln("Empty"); } return true; + + case ('3'): //ATI33 - Display the VC states + for (int vcIndex = 0; vcIndex < MAX_VC; vcIndex++) + { + systemPrint("VC "); + systemPrint(vcIndex); + systemPrint(": "); + systemPrintln(vcStateNames[virtualCircuitList[vcIndex].vcState]); + } + return true; + } } if ((commandString[2] == 'I') && (commandString[3] == '5') && (commandLength == 5)) diff --git a/Firmware/LoRaSerial/LoRaSerial.ino b/Firmware/LoRaSerial/LoRaSerial.ino index 82561953..4f688231 100644 --- a/Firmware/LoRaSerial/LoRaSerial.ino +++ b/Firmware/LoRaSerial/LoRaSerial.ino @@ -152,6 +152,9 @@ float *channels; uint8_t channelNumber = 0; uint32_t airSpeed; +uint16_t myRandSeed; +bool myRandBit; + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //Encryption diff --git a/Firmware/LoRaSerial/Radio.ino b/Firmware/LoRaSerial/Radio.ino index 39ac2f80..7b24cb57 100644 --- a/Firmware/LoRaSerial/Radio.ino +++ b/Firmware/LoRaSerial/Radio.ino @@ -482,9 +482,6 @@ uint16_t calcMaxThroughput() return (mostBytesPerSecond); } -uint16_t myRandSeed; -bool myRandBit; - //Generate unique hop table based on radio settings void generateHopTable() { diff --git a/Firmware/LoRaSerial/Serial.ino b/Firmware/LoRaSerial/Serial.ino index 7b1f7e55..ef5392e5 100644 --- a/Firmware/LoRaSerial/Serial.ino +++ b/Firmware/LoRaSerial/Serial.ino @@ -302,7 +302,7 @@ void updateSerial() //Assert RTS when there is enough space in the receive buffer if ((!rtsAsserted) && (availableRXBytes() < (sizeof(serialReceiveBuffer) / 2)) - && (availableTXBytes() <= RTS_ON_BYTES)) + && (availableTXBytes() <= settings.rtsOnBytes)) updateRTS(true); //We're ready for more data //Attempt to empty the serialTransmitBuffer diff --git a/Firmware/Tools/VcServerTest.c b/Firmware/Tools/VcServerTest.c index b0c62a30..5f3869c7 100644 --- a/Firmware/Tools/VcServerTest.c +++ b/Firmware/Tools/VcServerTest.c @@ -30,6 +30,7 @@ #define SET_PROGRAM_COMPLETE "ati12" #define START_3_WAY_HANDSHAKE "atc" +#define DEBUG_CMD_ISSUE 0 #define DEBUG_LOCAL_COMMANDS 0 #define DEBUG_PC_CMD_ISSUE 0 #define DEBUG_PC_TO_RADIO 0 @@ -64,28 +65,54 @@ { \ if (COMMAND_PENDING(queue, active)) \ { \ + if (DEBUG_CMD_ISSUE) \ + { \ + if (queue == pcCommandQueue) \ + printf("PC %s done\n", commandName[active]); \ + else \ + { \ + int vc = (&queue[0] - &virtualCircuitList[0].commandQueue[0]) \ + * sizeof(QUEUE_T) / sizeof(virtualCircuitList[0]); \ + printf("VC %d %s done\n", vc, commandName[active]); \ + } \ + } \ queue[active / QUEUE_T_BITS] &= ~(1 << (active & QUEUE_T_MASK)); \ active = CMD_LIST_SIZE; \ } \ } -#define COMMAND_ISSUE(queue, pollCount, cmd) \ -{ \ - /* Place the command in the queue */ \ - queue[cmd / QUEUE_T_BITS] |= 1 << (cmd & QUEUE_T_MASK); \ - \ - /* Timeout the command processor */ \ - if (!commandProcessorRunning) \ - commandProcessorRunning = STALL_CHECK_COUNT; \ - \ - /* Remember when this command was issued */ \ - if (!pollCount) \ - { \ - if (timeoutCount) \ - pollCount = timeoutCount; \ - else \ - pollCount = 1; \ - } \ +#define COMMAND_ISSUE(queue, pollCount, cmd) \ +{ \ + if (DEBUG_CMD_ISSUE) \ + { \ + if (!COMMAND_PENDING(queue, cmd)) \ + { \ + if (queue == pcCommandQueue) \ + printf("PC %s issued\n", commandName[cmd]); \ + else \ + { \ + int vc = (&queue[0] - &virtualCircuitList[0].commandQueue[0]) \ + * sizeof(QUEUE_T) / sizeof(virtualCircuitList[0]); \ + printf("VC %d %s issued\n", vc, commandName[cmd]); \ + } \ + } \ + } \ + \ + /* Place the command in the queue */ \ + queue[cmd / QUEUE_T_BITS] |= 1 << (cmd & QUEUE_T_MASK); \ + \ + /* Timeout the command processor */ \ + if (!commandProcessorRunning) \ + commandProcessorRunning = STALL_CHECK_COUNT; \ + \ + /* Remember when this command was issued */ \ + if (!pollCount) \ + { \ + if (timeoutCount) \ + pollCount = timeoutCount; \ + else \ + pollCount = 1; \ + } \ } #define COMMAND_PENDING(queue,cmd) ((queue[cmd / QUEUE_T_BITS] >> (cmd & QUEUE_T_MASK)) & 1) @@ -102,6 +129,7 @@ typedef enum //Connect to the remote radio CMD_AT_CMDVC, //Select target VC CMD_ATC, //Start the 3-way handshake + CMD_WAIT_CONNECTED, //Wait until the client is connected //Get remote radio connection status, type and ID @@ -443,6 +471,7 @@ int hostToStdout(VC_SERIAL_MESSAGE_HEADER * header, uint8_t * data, uint8_t byte //Write this data to stdout bytesSent = 0; status = 0; + fflush(stdout); while (bytesSent < bytesToSend) { bytesWritten = write(STDOUT, &data[bytesSent], bytesToSend - bytesSent); @@ -476,6 +505,12 @@ void radioToPcLinkStatus(VC_SERIAL_MESSAGE_HEADER * header, uint8_t * data, uint newState = vcMsg->vcState; virtualCircuitList[srcVc].vcState = newState; + //Display the state if requested + if (DISPLAY_STATE_TRANSITION || (newState == VC_STATE_LINK_DOWN) + || (previousState == VC_STATE_LINK_DOWN) + || ((newState != previousState) && (virtualCircuitList[srcVc].activeCommand < CMD_LIST_SIZE))) + printf("VC%d: %s --> %s\n", srcVc, vcStateNames[previousState], vcStateNames[newState]); + //Save the LoRaSerial radio's unique ID //Determine if the PC's value is valid memset(uniqueId, UNIQUE_ID_ERASE_VALUE, sizeof(uniqueId)); @@ -517,9 +552,6 @@ void radioToPcLinkStatus(VC_SERIAL_MESSAGE_HEADER * header, uint8_t * data, uint } } - //Display the state if requested - if (DISPLAY_STATE_TRANSITION) - printf("VC%d: %s --> %s\n", srcVc, vcStateNames[previousState], vcStateNames[newState]); switch (newState) { default: @@ -530,6 +562,9 @@ void radioToPcLinkStatus(VC_SERIAL_MESSAGE_HEADER * header, uint8_t * data, uint break; case VC_STATE_LINK_DOWN: + //Stop the command processing for this VC + virtualCircuitList[srcVc].activeCommand = CMD_LIST_SIZE; + virtualCircuitList[srcVc].commandTimer = 0; if (DEBUG_PC_CMD_ISSUE) printf("VC %d DOWN\n", srcVc); if (DISPLAY_VC_STATE) @@ -686,8 +721,27 @@ void radioCommandComplete(VC_SERIAL_MESSAGE_HEADER * header, uint8_t * data, uin //The command processor is still running commandProcessorRunning = STALL_CHECK_COUNT; - //Done with this command + //Validate the srcVc srcVc = header->radio.srcVc; + if (srcVc >= PC_REMOTE_COMMAND) + { + if (srcVc < (uint8_t)VC_RSVD_SPECIAL_VCS) + srcVc &= VCAB_NUMBER_MASK; + else + switch(srcVc) + { + default: + fprintf(stderr, "ERROR: Unknown VC: %d (0x%02x)\n", srcVc, srcVc); + exit(-2); + break; + + //Ignore this command + case (uint8_t)VC_UNASSIGNED: + return; + } + } + + //Done with this command if (srcVc == myVc) { if (pcActiveCommand < CMD_LIST_SIZE)