stingr lib for v8_1
Diff: Stingr.cpp
- Revision:
- 0:0159aa4d2062
diff -r 000000000000 -r 0159aa4d2062 Stingr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Stingr.cpp Mon Oct 29 12:45:27 2018 +0000 @@ -0,0 +1,761 @@ +/* + * 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; + } + } + } +} \ No newline at end of file