diff --git a/src/drivers/distance_sensor/airlango/isl2950.cpp b/src/drivers/distance_sensor/airlango/isl2950.cpp index e2a6be9fbda6..2c2e1759c890 100644 --- a/src/drivers/distance_sensor/airlango/isl2950.cpp +++ b/src/drivers/distance_sensor/airlango/isl2950.cpp @@ -362,23 +362,53 @@ ISL2950::collect() perf_begin(_sample_perf); /* clear buffer if last read was too long ago */ - //int64_t read_elapsed = hrt_elapsed_time(&_last_read); + int64_t read_elapsed = hrt_elapsed_time(&_last_read); // ----------------------- LANBAO SPECIFIC --------------------------- - //printf("enter ISL2950::collect() - reads from serial"); - uint8_t buffer[50]; - int bytes_available = 0; - // int bytes_processed = 0; - int bytes_read = 0; - // bool full_frame; -bytes_read = bytes_read; - bytes_read = ::read(_fd, buffer + bytes_available, 50 - bytes_available); - printf("read() returns %02X %02X %02X %02X \n", buffer[0], buffer[1],buffer[2],buffer[3] ); + uint8_t buffer[50]; + int bytes_available = 0; + int bytes_processed = 0; + int bytes_read = 0; + bool full_frame; + int distance_mm = -1.0f; + + bytes_read = ::read(_fd, buffer + bytes_available, 50 - bytes_available); + //printf("read() returns %02X %02X %02X %02X \n", buffer[0], buffer[1],buffer[2],buffer[3] ); //-------------------------------------------------------------------- + if (bytes_read < 0) { + PX4_ERR("isl2950 - read() error: %d \n", bytes_read); + perf_count(_comms_errors); + perf_end(_sample_perf); + + /* only throw an error if we time out */ + if (read_elapsed > (_conversion_interval * 2)) { + return bytes_read; + + } else { + return -EAGAIN; + } + + } else if (bytes_read == 0) { + return -EAGAIN; // SF0X drivers + // LANBAO driver + } + + bytes_available += bytes_read; + + // parse the buffer data + full_frame = false; + bytes_processed = isl2950_parser(buffer, bytes_available, &full_frame,&distance_mm); + bytes_processed = bytes_processed; + //printf("isl2950_parser() processed %d bytes, full_frame %d \n", bytes_processed, full_frame); + if (full_frame) { + printf("Measured Distance %d \n",distance_mm*100); + } + +// ---------------------------- END EDIT _last_read = hrt_absolute_time(); ret = OK; diff --git a/src/drivers/distance_sensor/airlango/isl2950_parser.cpp b/src/drivers/distance_sensor/airlango/isl2950_parser.cpp index 2f50974040cb..314244678b22 100644 --- a/src/drivers/distance_sensor/airlango/isl2950_parser.cpp +++ b/src/drivers/distance_sensor/airlango/isl2950_parser.cpp @@ -40,16 +40,164 @@ #include "isl2950_parser.h" #include #include +#include #include "isl2950_parser.h" #include #include +typedef unsigned char UCHAR; +typedef unsigned short USHORT; -int isl2950_parser(char c, char *parserbuf, unsigned *parserbuf_index, enum ISL2950_PARSE_STATE *state, float *dist) +// Note : No clue what those static variables are +static const UCHAR aucCRCHi[] = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40 +}; + +static const UCHAR aucCRCLo[] = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, + 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, + 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, + 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, + 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, + 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, + 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, + 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, + 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, + 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, + 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, + 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, + 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, + 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, + 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, + 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, + 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, + 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, + 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, + 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, + 0x41, 0x81, 0x80, 0x40 +}; + +// TOF frame format +// +// 1B 1B 1B 1B 2B +// | 0xA5 | 0x5A | distance-MSB | distance-LSB | crc-16 | +// +// Frame data saved for CRC calculation +const static int TOF_DISTANCE_MSB_POS = 2; +const static int TOF_DISTANCE_LSB_POS = 3; +const static int TOF_CRC_CALC_DATA_LEN = 4; +static unsigned char frame_data[TOF_CRC_CALC_DATA_LEN] = { + TOF_SFD1, TOF_SFD2, 0, 0 +}; + +USHORT usMBCRC16(UCHAR* pucFrame, USHORT usLen) { + UCHAR ucCRCHi = 0xFF; + UCHAR ucCRCLo = 0xFF; + int iIndex; + while (usLen--) { + iIndex = ucCRCLo ^ *(pucFrame++); + ucCRCLo = (UCHAR)(ucCRCHi ^ aucCRCHi[iIndex]); + ucCRCHi = aucCRCLo[iIndex]; + } + return (USHORT)(ucCRCHi << 8 | ucCRCLo); +} + +int isl2950_parser(const uint8_t* buffer, int length, bool* full_frame, int* dist) { + static TofFramingState state = TFS_NOT_STARTED; + static uint16_t crc16 = 0; int bytes_processed = 0; -// SOME STUFFS + while (bytes_processed < length) { + uint8_t b = buffer[bytes_processed++]; +// printf("parse byte 0x%02X \n", b); + + switch (state) { + case TFS_NOT_STARTED: + if (b == TOF_SFD1) { + state = TFS_GOT_SFD1; + // printf("Got SFD1 \n"); + } + break; + + case TFS_GOT_SFD1: + if (b == TOF_SFD2) { + state = TFS_GOT_SFD2; +// printf("Got SFD2 \n"); + } else if (b == TOF_SFD1) { + state = TFS_GOT_SFD1; +// printf("Discard previous SFD1, Got new SFD1 \n"); + } else { + state = TFS_NOT_STARTED; + } + break; + + case TFS_GOT_SFD2: + frame_data[TOF_DISTANCE_MSB_POS] = b; + state = TFS_GOT_DATA1; +// printf("Got DATA1 0x%02X \n", b); + break; + + case TFS_GOT_DATA1: + frame_data[TOF_DISTANCE_LSB_POS] = b; + state = TFS_GOT_DATA2; +// printf("Got DATA2 0x%02X \n", b); + // do crc calculation + crc16 = usMBCRC16(frame_data, TOF_CRC_CALC_DATA_LEN); + // convert endian + crc16 = (crc16 >> 8) | (crc16 << 8); + break; + + case TFS_GOT_DATA2: + if (b == (crc16 >> 8)) { + state = TFS_GOT_CHECKSUM1; + } else { +// printf("Checksum invalid on high byte: 0x%02X, calculated: 0x%04X \n",b, crc16); + state = TFS_NOT_STARTED; + } + break; + + case TFS_GOT_CHECKSUM1: + // Here, reset state to `NOT-STARTED` no matter crc ok or not + state = TFS_NOT_STARTED; + if (b == (crc16 & 0xFF)) { + printf("Checksum verified \n"); + *dist = (frame_data[TOF_DISTANCE_MSB_POS] << 8) | frame_data[TOF_DISTANCE_LSB_POS]; + *full_frame = true; + return bytes_processed; + } else { + printf("Checksum invalidon low byte: 0x%02X, calculated: 0x%04X \n",b, crc16); + } + break; + + default: + printf("This should never happen. \n"); + break; + } + } + // SOME STUFFS return bytes_processed; } diff --git a/src/drivers/distance_sensor/airlango/isl2950_parser.h b/src/drivers/distance_sensor/airlango/isl2950_parser.h index 6e4b3a9f9da6..b12bc53008cb 100644 --- a/src/drivers/distance_sensor/airlango/isl2950_parser.h +++ b/src/drivers/distance_sensor/airlango/isl2950_parser.h @@ -40,6 +40,27 @@ #pragma once +// frame start delimiter +#define TOF_SFD1 0xA5 +#define TOF_SFD2 0x5A + +typedef enum { + TFS_NOT_STARTED = 0, + TFS_GOT_SFD1, + TFS_GOT_SFD2, + TFS_GOT_DATA1, + TFS_GOT_DATA2, + TFS_GOT_CHECKSUM1, + TFS_GOT_CHECKSUM2, +} TofFramingState; + +enum IslWorkingMode { + KEEP_HEIGHT = 0, + NUM_WORKING_MODE +}; + + +// SF0X STYLE enum ISL2950_PARSE_STATE { ISL2950_PARSE_STATE0_UNSYNC = 0, ISL2950_PARSE_STATE1_SYNC, @@ -50,4 +71,5 @@ enum ISL2950_PARSE_STATE { ISL2950_PARSE_STATE6_GOT_CARRIAGE_RETURN }; -int isl2950_parser(char c, char *parserbuf, unsigned *parserbuf_index, enum ISL2950_PARSE_STATE *state, float *dist); + +int isl2950_parser(const uint8_t* buffer, int length, bool* full_frame, int* dist);