//************************************* // FrSky Telemetry serial code * // By Midelic on RCGroups * //************************************* #if defined TELEMETRY #if defined SPORT_TELEMETRY #define SPORT_TIME 12000 #define FRSKY_SPORT_PACKET_SIZE 8 uint32_t last = 0; uint8_t sport_counter=0; uint8_t RxBt = 0; uint8_t rssi; uint8_t sport = 0; #endif #if defined HUB_TELEMETRY #define USER_MAX_BYTES 6 uint8_t prev_index; #endif #define START_STOP 0x7e #define BYTESTUFF 0x7d #define STUFF_MASK 0x20 #define MAX_PKTX 10 uint8_t pktx[MAX_PKTX]; uint8_t index; uint8_t pass = 0; uint8_t frame[18]; #if defined DSM_TELEMETRY void DSM2_frame() { Serial_write(0xAA); // Start for (uint8_t i = 0; i < 17; i++) // RSSI value followed by 16 bytes of telemetry data Serial_write(pkt[i]); } #endif void frskySendStuffed() { Serial_write(START_STOP); for (uint8_t i = 0; i < 9; i++) { if ((frame[i] == START_STOP) || (frame[i] == BYTESTUFF)) { Serial_write(BYTESTUFF); frame[i] ^= STUFF_MASK; } Serial_write(frame[i]); } Serial_write(START_STOP); } void compute_RSSIdbm() { RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>4); if(pktt[len-2] >=128) RSSI_dBm -= 164; else RSSI_dBm += 130; } void frsky_check_telemetry(uint8_t *pkt,uint8_t len) { if(pkt[1] == rx_tx_addr[3] && pkt[2] == rx_tx_addr[2] && len ==(pkt[0] + 3)) { for (uint8_t i=3;i> 4 & 0x0f) == 0x08) { seq_last_sent = 8; seq_last_rcvd = 0; pass=0; } else { if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4) seq_last_rcvd = (seq_last_rcvd + 1) % 4; else pass=0;//reset if sequence wrong } } #endif } } void frsky_link_frame() { frame[0] = 0xFE; if ((cur_protocol[0]&0x1F)==MODE_FRSKY) { compute_RSSIdbm(); frame[1] = pktt[3]; frame[2] = pktt[4]; frame[3] = pktt[5]; frame[4] = (uint8_t)RSSI_dBm; } else if ((cur_protocol[0]&0x1F)==MODE_HUBSAN) { frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V frame[2] = frame[1]; frame[3] = 0x00; frame[4] = (uint8_t)RSSI_dBm; } frame[5] = frame[6] = frame[7] = frame[8] = 0; frskySendStuffed(); } #if defined HUB_TELEMETRY void frsky_user_frame() { uint8_t indexx = 0, c=0, j=8, n=0, i; if(pktt[6]>0 && pktt[6]<=10) {//only valid hub frames frame[0] = 0xFD; frame[2] = pktt[7]; switch(pass) { case 0: indexx=pktt[6]; for(i=0;i0) { crc_s += p[i]; //0-1FF crc_s += crc_s >> 8; //0-100 crc_s &= 0x00ff; } } } void sportIdle() { Serial_write(START_STOP); } void sportSendFrame() { uint8_t i; sport_counter = (sport_counter + 1) %36; if(sport_counter<3) { frame[0] = 0x98; frame[1] = 0x10; for (i=5;i<8;i++) frame[i]=0; } switch (sport_counter) { case 0: frame[2] = 0x05; frame[3] = 0xf1; frame[4] = 0x20;//dummy values if swr 20230f00 frame[5] = 0x23; frame[6] = 0x0F; break; case 1: // RSSI frame[2] = 0x01; frame[3] = 0xf1; frame[4] = rssi; break; case 2: //BATT frame[2] = 0x04; frame[3] = 0xf1; frame[4] = RxBt;//a1; break; default: if(sport) { for (i=0;i= FRSKY_SPORT_PACKET_SIZE) {//8 bytes no crc sport = 1;//ok to send pass = 0;//reset } } #endif void frskyUpdate() { #if defined DSM_TELEMETRY if(telemetry_link && (cur_protocol[0]&0x1F) == MODE_DSM2 ) { // DSM2 DSM2_frame(); telemetry_link=0; return; } #endif if(telemetry_link && (cur_protocol[0]&0x1F) != MODE_FRSKYX ) { // FrSky + Hubsan frsky_link_frame(); telemetry_link=0; return; } #if defined HUB_TELEMETRY if(!telemetry_link && (cur_protocol[0]&0x1F) == MODE_FRSKY) { // FrSky frsky_user_frame(); return; } #endif #if defined SPORT_TELEMETRY if ((cur_protocol[0]&0x1F)==MODE_FRSKYX) { // FrSkyX if(telemetry_link) { if(pktt[4]>0x36) rssi=pktt[4]>>1; else RxBt=pktt[4]; for (uint8_t i=0; i < pktt[6]; i++) proces_sport_data(pktt[7+i]); telemetry_link=0; } uint32_t now = micros(); if ((now - last) > SPORT_TIME) { sportSendFrame(); last = now; } } #endif } #endif