stingr lib for v8_1
Stingr.cpp
- Committer:
- jmoreno10
- Date:
- 2018-10-29
- Revision:
- 0:0159aa4d2062
File content as of revision 0:0159aa4d2062:
/* * mbed STINGR Library * Copyright (c) 2018 * * 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 "Stingr.h" #include "mbed.h" #include "rtos.h" #define QUERY_ESN 'a' #define QUERY_BURSTS 'b' #define QUERY_FIRMWARE 'c' #define QUERY_SETUP 'd' #define QUERY_HARDWARE 'e' #define NAK_COMMAND 'f' #define SETUP 'g' #define SEND_DATA 'h' #define ABORT_TRANSMISSION 'i' // These two lines redundant? Serial _stingrUART(p13, p14, 9600); // tx, rx Comunicación Serial con el STINGR Serial _pc(USBTX, USBRX, 9600); // tx, rx Comunicación Serial con la PC // Pin Digital de entrada "CTS" en modo Pull-Up // para encontrarse normalmente a VCC cuando no haya un pulso. DigitalIn _CTS(p11, PullUp); // Pin Digital de Salida "RTS" // Predefinido para valer 1 en su estado inactivo dentro del código. DigitalOut _RTS(p12, 1); DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); // Constructor Stingr::Stingr() { incomingByte = 0; flag = 1; num = 0; incomingByteR = 0; incomingByteX = 0; // For Luis Fernando: // This thread is for the Mbed to read and serial print responses from STINGR t1.start(callback(this,&Stingr::respuesta)); // For Luis Fernando: // This thread is for reading commands from serial PC. (May be commented) t2.start(callback(this,&Stingr::PC_communication)); } // Accessor const char* Stingr::get_resp() const { return _resp; } // Mutator void Stingr::setPacketByte(int incomingByte) { _packet[num] = incomingByte; num++; } /******************************************************************************/ /********************[SERIAL PACKET PROCESSING FUNCTIONS]**********************/ /******************************************************************************/ void Stingr::clearPacket() { num = 0; for(int i = 0; i < 15 ; i++) _packet[i] = 0; } void Stingr::printPacket() { _pc.printf("\nResponse(Stingr)dec: \t"); for(int i = 0; i < 15 ; i++) { _pc.printf("%u",_packet[i]); // Format specifier _pc.printf(" "); } } void Stingr::waitCTS() { Thread::wait(200); // Se da un tiempo para que el analizador se estabilice incomingByte=0; //pc.printf("El valor de CTS es %d\n\r",CTS.read()); // Se lee el valor de la variable CTS, la cual debe ser 1 //pc.printf("El valor de RTS es %d\n\r",RTS.read()); // Se lee el valor de la variable RTS, la cual debe ser 1 _RTS=0; // Se manda un pulso en bajo en RTS, para inicial el proceso de transmisión while(flag==1) {// Flag inicialmente vale 1, así que el ciclo while cambiará hasta que esa condición no se cumpla flag=_CTS.read(); // Cuando entra el ciclo, se iguala flag a CTS, el cual cuando cambie a 0 provocará que termine el while (máx 125 ms) //pc.printf("El valor de flag es %d\n\r", flag); // Se imprime el valor de flag, para identificar cuando termina el ciclo while } } void Stingr::postCommand() { Thread::wait(10); // Se esperan .1 segundos una vez que se terminaron de hacer las transmisiones //El tiempo total de transmisión es; el wait previo a las transmisiones, el tiempo que tarda el Mu en enviar los datos y el wait posterior a la transmisión _RTS=1; Thread::wait(150); //pc.printf("\n\rCTS: %d\n\r",CTS.read()); flag=1; } void Stingr::command(char* com) { char c = com[0]; switch(c) { case QUERY_ESN: query_ESN(); break; case QUERY_BURSTS: query_Bursts(); break; case QUERY_FIRMWARE: query_Firmware(); break; case QUERY_SETUP: query_Setup(); break; case QUERY_HARDWARE: query_Hardware(); break; case NAK_COMMAND: NAK_command(); break; case SETUP: _setup(com); //* later make this function to pass buf parameter break; case SEND_DATA: send_Data(com); break; case ABORT_TRANSMISSION: abort_Transmission(); break; default: { //do nothing } } } void Stingr::execute(char* com) { char c = com[0]; switch(c) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': // if 'a'-'i', set _resp to garbage for 1st call strncpy(_resp,"garbage",sizeof(_resp)); break; default: { // do nothing for 2nd call. } } } /******************************************************************************/ /************************[STINGR COMMAND FUNCTIONS]****************************/ /******************************************************************************/ //0x01 Query ESN void Stingr::query_ESN() { led1=!led1; _pc.printf("\r0x01\t\t\tQuery ESN\n"); _pc.printf("Command(HEX):\t\tAA 5 1 50 D5\n\r"); _pc.printf("Response(Stingr)HEX:\t"); waitCTS(); Thread::wait(10); _stingrUART.putc(0XAA); _stingrUART.putc(0X05); _stingrUART.putc(0X01); _stingrUART.putc(0X50); _stingrUART.putc(0XD5); postCommand(); printPacket(); // Correct ESN if (_packet[3] == 0 && // 0x00 _packet[4] == 41 && // 0x29 _packet[5] == 72 && // 0x48 //0x43 STINGR TLE _packet[6] == 254) // 0xFE //0xB3 STINGR TLE { clearPacket(); _pc.printf("\nQuery ESN is correct. VALID\n"); strncpy(_resp,"Query ESN is correct",sizeof(_resp)); } // Wrong ESN else { clearPacket(); _pc.printf("\nNAK response. INVALID\n"); strncpy(_resp,"NAK response (Query ESN)",sizeof(_resp)); } } //0x04 Query Bursts void Stingr::query_Bursts() { int bursts = 0; //default value led2=!led2; _pc.printf("\r0x04\t\t\tQuery Burst Remaining\n"); _pc.printf("Command(HEX):\t\tAA 5 4 FD 82\n\r"); _pc.printf("Response(Stingr)HEX:\t"); waitCTS(); Thread::wait(10); _stingrUART.putc(0XAA); _stingrUART.putc(0X05); _stingrUART.putc(0X04); _stingrUART.putc(0XFD); _stingrUART.putc(0X82); postCommand(); printPacket(); // NAK response if (_packet[0] == 170 && // 0xAA _packet[1] == 5 && // 0x05 _packet[2] == 255 && // 0xFF _packet[3] == 161 && // 0xA1 _packet[4] == 203) // 0xCB { clearPacket(); _pc.printf("\nNAK response. INVALID"); strncpy(_resp,"NAK response (Query Bursts)",sizeof(_resp)); } // ACK response else { bursts = _packet[3]; clearPacket(); char qry[2]; sprintf(qry,"%d",bursts); char strt[] = "Bursts Remaining is "; strcat(strt,qry); _pc.printf("\nBursts Remaining: \t"); _pc.printf("%u",bursts); _pc.printf("\n"); strncpy(_resp,strt,sizeof(_resp)); } } //0x05 Query Firmware void Stingr::query_Firmware() { led3=!led3; _pc.printf("\r0x05\t\t\tQuery Firmware Version\n"); _pc.printf("Command(HEX):\t\tAA 5 5 74 93\n\r"); _pc.printf("Response(Stingr)HEX:\t"); waitCTS(); Thread::wait(10); _stingrUART.putc(0XAA); _stingrUART.putc(0X05); _stingrUART.putc(0X05); _stingrUART.putc(0X74); _stingrUART.putc(0X93); postCommand(); printPacket(); if (_packet[3] == 1 && // 0x01 _packet[4] == 3) // 0x03 { clearPacket(); _pc.printf("\nResponse Processing:\tQuery Firmware is correct. VALID\n"); _pc.printf(" Firmware Version: 1.3\n"); strncpy(_resp,"Query Firmware is correct",sizeof(_resp)); } else { clearPacket(); _pc.printf("NAK. INVALID"); strncpy(_resp,"NAK response (Query Firmware)",sizeof(_resp)); } } //0x07 Query Setup void Stingr::query_Setup() { int numSetup = 0; led4=!led4; _pc.printf("\r0x07\t\t\tQuery Setup\n"); _pc.printf("Command(HEX):\t\tAA 5 7 66 B0\n\r"); _pc.printf("Response(Stingr)HEX:\t"); waitCTS(); Thread::wait(10); _stingrUART.putc(0XAA); _stingrUART.putc(0X05); _stingrUART.putc(0X07); _stingrUART.putc(0X66); _stingrUART.putc(0XB0); postCommand(); // NAK response if (_packet[0] == 170 && // 0xAA _packet[1] == 5 && // 0x05 _packet[2] == 255 && // 0xFF _packet[3] == 161 && // 0xA1 _packet[4] == 203) // 0xCB { clearPacket(); _pc.printf("NAK"); } // ACK response else { numSetup = _packet[7]*10000000 + _packet[8]*100000 + _packet[9]*1000 + _packet[10]; clearPacket(); char qryRF[1]; char qryBursts[2]; char qryMin[3]; char qryMax[3]; char strt[] = ""; //Print Channel _pc.printf("\n RF Channel: "); _pc.printf("%u",numSetup/(10000000)); int rfprint = numSetup/(10000000); // RF channel sprintf(qryRF,"%d",rfprint); strcat(strt,qryRF); numSetup = numSetup - (numSetup/10000000)*10000000; // Truncate RF Digits //Print Bursts _pc.printf("\n # of Bursts: "); _pc.printf("%u",numSetup/(100000)); // Bursts Per Message int burprint = numSetup/(100000); sprintf(qryBursts,"%d",burprint); strcat(strt,qryBursts); numSetup = numSetup - (numSetup/100000)*100000; // Truncate Burst Digits //Print Min Interval _pc.printf("\n Min Burst Interval: "); _pc.printf("%u",numSetup/1000*5); // Min Interval int minprint = numSetup/1000*5; sprintf(qryMin,"%d",minprint); strcat(strt,qryMin); numSetup = numSetup - (numSetup/1000)*1000; // Truncate Min Interval _pc.printf(" seconds"); //Print Max Interval _pc.printf("\n Max Burst Interval: "); _pc.printf("%u",numSetup*5); int maxprint = numSetup*5; // Max Interval sprintf(qryMax,"%d",maxprint); strcat(strt,qryMax); _pc.printf(" seconds\n"); strncpy(_resp,strt,sizeof(_resp)); } } //0x09 Query Hardware void Stingr::query_Hardware() { led1=!led1; _pc.printf("\r0x09\t\t\tQuery Hardware Version\n"); _pc.printf("Command(HEX):\t\tAA 5 9 18 59\n\r"); _pc.printf("Response(Stingr)HEX:\t"); waitCTS(); Thread::wait(10); _stingrUART.putc(0XAA); _stingrUART.putc(0X05); _stingrUART.putc(0X09); _stingrUART.putc(0X18); _stingrUART.putc(0X59); postCommand(); printPacket(); // ACK response if (_packet[5] == 143 && // 0x8F _packet[6] == 98 && // 0x62 _packet[7] == 98) // 0x62 { clearPacket(); _pc.printf("\nResponse Processing:\tQuery Hardware is correct. VALID\n"); _pc.printf(" Device Code: 01\n"); _pc.printf(" CPU Revision: 62\n"); _pc.printf(" Radio Revision: 62\n"); strncpy(_resp,"Query Hardware is correct",sizeof(_resp)); } // NAK response else { clearPacket(); _pc.printf("\n"); _pc.printf("NAK. INVALID"); strncpy(_resp,"NAK response (Query Hardware)",sizeof(_resp)); } } //NAK Command void Stingr::NAK_command() { led2=!led2; _pc.printf("\rXxXX\t\t\tNAK\n"); _pc.printf("Command(HEX):\t\tAA 5 7 66 B1\n\r"); _pc.printf("Response(Stingr)HEX:\t"); waitCTS(); Thread::wait(10); _stingrUART.putc(0XAA); _stingrUART.putc(0X05); _stingrUART.putc(0X07); _stingrUART.putc(0X66); _stingrUART.putc(0XB1); postCommand(); printPacket(); clearPacket(); _pc.printf("\n"); strncpy(_resp,"NAK response",sizeof(_resp)); } //0x06 Setup void Stingr::_setup(char* b) { led3=!led3; _pc.printf("\r0x06\t\t\tSetup\n"); //_pc.printf("Command(HEX):\t\tAA 0E 06 00 00 00 00 00 03 18 30 00 CE 9C\n\r"); // RF Channel int rf = b[1] - '0'; _pc.printf("rf channel: %u \n",rf); // Bursts int brst = b[2] - '0'; _pc.printf("bursts: %u \n", brst); // Min Interval int min_hund = b[3] - '0'; int min_tens = b[4] - '0'; int min_ones = b[5] - '0'; //_pc.printf("Min interval: %u%u%u seconds\n", min_hund, min_tens, min_ones); int min_int = (min_hund*100 + min_tens*10 + min_ones)/5; _pc.printf("Min interval: %u seconds\n", min_int*5); // Max Interval int max_hund = b[6] - '0'; int max_tens = b[7] - '0'; int max_ones = b[8] - '0'; //_pc.printf("Max interval: %u%u%u seconds\n", max_hund, max_tens, max_ones); int max_int = (max_hund*100 + max_tens*10 + max_ones)/5; _pc.printf("Max interval: %u seconds\n", max_int*5); char header[12] = {0xAA,0x0E,0x06,0x00,0x00,0x00,0x00,rf,brst,min_int,max_int,0x00}; _pc.printf("Command(HEX):\t\t"); //Print b characters in HEX for(int k = 0; k < 12; k++) _pc.printf("%X ",header[k]); // CRC calculation char *t = (char *)header; //a char crc1 = ModRTU_CRC(t,t[1]-2)&0xFF; char crc2 = ModRTU_CRC(t,t[1]-2)>>8; _pc.printf("%X ",crc1); //%X print char in HEX format _pc.printf("%X ",crc2); //%X print char in HEX format _pc.printf("\nResponse(Stingr)HEX:\t"); waitCTS(); Thread::wait(10); //Send Command to STINGR for(int k = 0; k < 12; k++) _stingrUART.putc(header[k]); _stingrUART.putc(crc1); _stingrUART.putc(crc2); /* _stingrUART.putc(0XAA); _stingrUART.putc(0X0E); _stingrUART.putc(0X06); _stingrUART.putc(0X00); _stingrUART.putc(0X00); _stingrUART.putc(0X00); _stingrUART.putc(0X00); _stingrUART.putc(0X00); _stingrUART.putc(0X03); _stingrUART.putc(0X18); _stingrUART.putc(0X30); _stingrUART.putc(0X00); _stingrUART.putc(0XCE); _stingrUART.putc(0X9C); */ postCommand(); printPacket(); _pc.printf("\n"); clearPacket(); } //0x00 Send Data void Stingr::send_Data(char* b) //char* s //Replace "buf" with "b" { led4=!led4; // Count all characters before the "Return" key in the buffer int cnt = 0; for (int k = 0; k < 200; k++) { if(b[k] == '\n') break; cnt++; } // Print command info and input _pc.printf("0x00\t\t\tSend Data\n\r"); cnt--; //Decrement total by 1. Don't count 8/h. _pc.printf("Data Packet length: \t%u\n",cnt); // Port b array to str, but without first character '8/h' char str[cnt]; //Declare str array. str will copy buf but without '8' for (int k = 0; k < cnt; k++) str[k] = b[k+1]; //Starts 1 index after '8'. // str1 copies str but with correct datalength by truncating the extra characters // found in str char str1[cnt]; strncpy(str1,str,cnt); //truncation of extra characters str1[cnt] = '\0'; //Null character _pc.printf("Data Packet: \t\t%s \n",str1); //--------------------replace b with str1 waitCTS(); Thread::wait(10); // Put str "data" into Serial packet array (to send to STINGR) size_t n = strlen(str1); //Measure size of b. This includes the zeros //!replaced int number = n+3; int len = n+5; char header[3] = {0xAA,len,0x00}; //Define header information char vec[number]; //pc.printf("number = %u\n",number); //store all in vec for(int k = 0; k < 3; k++) vec[k] = header[k]; for(int k = 3; k < number; k++) vec[k] = str1[k-3];//!replaced _pc.printf("Command(HEX):\t\t"); //Print b characters in HEX for(int k = 0; k < number; k++) _pc.printf("%X ",vec[k]); // CRC calculation char *t = (char *)vec; //a char crc1 = ModRTU_CRC(t,t[1]-2)&0xFF; char crc2 = ModRTU_CRC(t,t[1]-2)>>8; _pc.printf("%X ",crc1); //%X print char in HEX format _pc.printf("%X ",crc2); //%X print char in HEX format _pc.printf("\nResponse(Stingr)HEX:\t"); //Send Command to STINGR for(int k = 0; k < number; k++) _stingrUART.putc(vec[k]); _stingrUART.putc(crc1); _stingrUART.putc(crc2); postCommand(); printPacket(); // NAK response if (_packet[0] == 170 && // 0xAA _packet[1] == 5 && // 0x05 _packet[2] == 255 && // 0xFF _packet[3] == 161 && // 0xA1 _packet[4] == 203) // 0xCB { clearPacket(); _pc.printf("\n"); _pc.printf("\nNAK response. INVALID"); strncpy(_resp,"NAK response (Send Data)",sizeof(_resp)); } // ACK response else { clearPacket(); _pc.printf("\n"); _pc.printf("\nSend Data is successful. VALID\n"); strncpy(_resp,"Send Data is successful",sizeof(_resp)); } } //0x03 Abort Transmission void Stingr::abort_Transmission() { led1=!led1; _pc.printf("\r0x03\t\t\tAbort Transmission\n"); _pc.printf("Command(HEX):\t\tAA 5 3 42 F6\n\r"); _pc.printf("Response(Stingr)HEX:\t"); waitCTS(); Thread::wait(10); _stingrUART.putc(0XAA); _stingrUART.putc(0X05); _stingrUART.putc(0X03); _stingrUART.putc(0X42); _stingrUART.putc(0XF6); postCommand(); printPacket(); // ACK response if (_packet[0] == 170 && // 0xAA _packet[1] == 5 && // 0x05 _packet[2] == 3 && // 0x03 _packet[3] == 66 && // 0x42 _packet[4] == 246) // 0xF6 { clearPacket(); _pc.printf("\nResponse Processing:\tTransmission successfully aborted.\n"); strncpy(_resp,"Transmission successfully aborted.",sizeof(_resp)); } // NAK response else { clearPacket(); _pc.printf("\nResponse Processing:\tNAK response. INVALID"); strncpy(_resp,"NAK response (Abort Transmission)",sizeof(_resp)); } } uint16_t Stingr::ModRTU_CRC(char * buf, int len) { unsigned char i; unsigned short data; uint16_t crc = 0xFFFF; do{ data = (unsigned int)0x00FF & *buf++; crc = crc ^ data; for(i = 8; i > 0; i--) { if(crc & 0x0001) crc = (crc >> 1) ^ 0x8408; else crc >>=1; } }while (--len); crc = ~crc; // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes) return (crc); } void Stingr::respuesta() { while(1) { if(_stingrUART.readable()) { // Se esperan datos provenientes del TX del módulo STX3 incomingByteR = _stingrUART.getc(); //stingr.setPacketByte(incomingByteR); setPacketByte(incomingByteR); _pc.printf("%X",incomingByteR); // Format specifier _pc.printf(" "); } } } // Thread 2: Reading commands from PC void Stingr::PC_communication() { int a = 0; while(1) { char str1[200]; if (_pc.readable()) { incomingByteX = _pc.getc(); strx[a] = incomingByteX; a++; if(incomingByteX == '\n') { _pc.printf("\n\nPC input: \t\t"); strncpy(str1,strx,sizeof(strx)); _pc.printf("%s",str1); _pc.printf("\n"); //stingr.command(str1); command(str1); memset(strx, 0, 200); a = 0; } } } }