int configure_gps_ubx(int *fd) { // only needed once like this const type_gps_bin_cfg_prt_packet_t cfg_prt_packet = { .clsID = UBX_CLASS_CFG, .msgID = UBX_MESSAGE_CFG_PRT, .length = UBX_CFG_PRT_LENGTH, .portID = UBX_CFG_PRT_PAYLOAD_PORTID, .mode = UBX_CFG_PRT_PAYLOAD_MODE, .baudRate = current_gps_speed, .inProtoMask = UBX_CFG_PRT_PAYLOAD_INPROTOMASK, .outProtoMask = UBX_CFG_PRT_PAYLOAD_OUTPROTOMASK, .ck_a = 0, .ck_b = 0 }; // only needed once like this const type_gps_bin_cfg_nav5_packet_t cfg_nav5_packet = { .clsID = UBX_CLASS_CFG, .msgID = UBX_MESSAGE_CFG_NAV5, .length = UBX_CFG_NAV5_LENGTH, .mask = UBX_CFG_NAV5_PAYLOAD_MASK, .dynModel = UBX_CFG_NAV5_PAYLOAD_DYNMODEL, .fixMode = UBX_CFG_NAV5_PAYLOAD_FIXMODE, .ck_a = 0, .ck_b = 0 }; // this message is reusable for different configuration commands, so not const type_gps_bin_cfg_msg_packet cfg_msg_packet = { .clsID = UBX_CLASS_CFG, .msgID = UBX_MESSAGE_CFG_MSG, .length = UBX_CFG_MSG_LENGTH, .rate = UBX_CFG_MSG_PAYLOAD_RATE }; uint64_t time_before_config = hrt_absolute_time(); while(hrt_absolute_time() < time_before_config + UBX_CONFIG_TIMEOUT) { // if (gps_verbose) printf("[gps] ubx config state: %d\n", ubx_config_state); switch (ubx_config_state) { case UBX_CONFIG_STATE_PRT: // if (gps_verbose) printf("[gps] Configuring ubx with baudrate: %d\n", cfg_prt_packet.baudRate); write_config_message_ubx((uint8_t*)(&cfg_prt_packet), sizeof(cfg_prt_packet), fd); break; case UBX_CONFIG_STATE_NAV5: write_config_message_ubx((uint8_t*)(&cfg_nav5_packet), sizeof(cfg_nav5_packet), fd); break; case UBX_CONFIG_STATE_MSG_NAV_POSLLH: cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV; cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_POSLLH; write_config_message_ubx((uint8_t*)(&cfg_msg_packet), sizeof(cfg_msg_packet), fd); break; case UBX_CONFIG_STATE_MSG_NAV_TIMEUTC: cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV; cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_TIMEUTC; write_config_message_ubx((uint8_t*)(&cfg_msg_packet), sizeof(cfg_msg_packet), fd); break; case UBX_CONFIG_STATE_MSG_NAV_DOP: cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV; cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_DOP; write_config_message_ubx((uint8_t*)(&cfg_msg_packet), sizeof(cfg_msg_packet), fd); break; case UBX_CONFIG_STATE_MSG_NAV_SVINFO: cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV; cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_SVINFO; write_config_message_ubx((uint8_t*)(&cfg_msg_packet), sizeof(cfg_msg_packet), fd); break; case UBX_CONFIG_STATE_MSG_NAV_SOL: cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV; cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_SOL; write_config_message_ubx((uint8_t*)(&cfg_msg_packet), sizeof(cfg_msg_packet), fd); break; case UBX_CONFIG_STATE_MSG_NAV_VELNED: cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV; cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_VELNED; write_config_message_ubx((uint8_t*)(&cfg_msg_packet), sizeof(cfg_msg_packet), fd); break; case UBX_CONFIG_STATE_MSG_RXM_SVSI: cfg_msg_packet.msgClass_payload = UBX_CLASS_RXM; cfg_msg_packet.msgID_payload = UBX_MESSAGE_RXM_SVSI; write_config_message_ubx((uint8_t*)(&cfg_msg_packet), sizeof(cfg_msg_packet), fd); break; case UBX_CONFIG_STATE_CONFIGURED: if (gps_verbose) printf("[gps] ubx configuration finished\n"); printf("\nGPS CONFIGURED\n"); thread_should_exit = true; return OK; break; default: break; } usleep(10000); } if (gps_verbose) printf("[gps] ubx configuration timeout\n"); return ERROR; } int read_gps_ubx(int *fd, char *gps_rx_buffer, int buffer_size) { uint8_t ret = 0; uint8_t c; int rx_count = 0; int gpsRxOverflow = 0; struct pollfd fds; fds.fd = *fd; fds.events = POLLIN; // UBX GPS mode // This blocks the task until there is something on the buffer while (1) { //check if the thread should terminate if (terminate_gps_thread == true) { ret = 1; break; } if (poll(&fds, 1, 1000) > 0) { if (read(*fd, &c, 1) > 0) { // printf("Read %x\n",c); if (rx_count >= buffer_size) { // The buffer is already full and we haven't found a valid ubx sentence. // Flush the buffer and note the overflow event. gpsRxOverflow++; rx_count = 0; ubx_decode_init(); if (gps_verbose) printf("[gps] Buffer full\n"); } else { //gps_rx_buffer[rx_count] = c; rx_count++; } int msg_read = ubx_parse(c, gps_rx_buffer); if (msg_read > 0) { //printf("Found sequence\n"); break; } } else { break; } } else { break; } } return ret; } int write_config_message_ubx(const uint8_t *message, const size_t length, const int *fd) { uint8_t ck_a = 0; uint8_t ck_b = 0; unsigned int i; uint8_t buffer[2]; ssize_t result_write = 0; //calculate and write checksum to the end for (i = 0; i < length-2; i++) { ck_a = ck_a + message[i]; ck_b = ck_b + ck_a; } // write sync bytes first buffer[0] = UBX_SYNC_1; buffer[1] = UBX_SYNC_2; // write config message without the checksum result_write = write(*fd, buffer, sizeof(buffer)); result_write += write(*fd, message, length-2); buffer[0] = ck_a; buffer[1] = ck_b; // write the checksum result_write += write(*fd, buffer, sizeof(buffer)); fsync(*fd); if ((unsigned int)result_write != length + 2) return ERROR; return OK; }
int read_gps_ubx(int *fd, char *gps_rx_buffer, int buffer_size) { uint8_t ret = 0; uint8_t c; int rx_count = 0; int gpsRxOverflow = 0; struct pollfd fds; fds.fd = *fd; fds.events = POLLIN; // UBX GPS mode // This blocks the task until there is something on the buffer while (1) { //check if the thread should terminate if (terminate_gps_thread == true) { // printf("terminate_gps_thread=%u ", terminate_gps_thread); // printf("exiting mtk thread\n"); // fflush(stdout); ret = 1; break; } if (poll(&fds, 1, 1000) > 0) { if (read(*fd, &c, 1) > 0) { // printf("Read %x\n",c); if (rx_count >= buffer_size) { // The buffer is already full and we haven't found a valid ubx sentence. // Flush the buffer and note the overflow event. gpsRxOverflow++; rx_count = 0; ubx_decode_init(); if (gps_verbose) printf("[gps] Buffer full\n"); } else { //gps_rx_buffer[rx_count] = c; rx_count++; } int msg_read = ubx_parse(c, gps_rx_buffer); if (msg_read > 0) { // printf("Found sequence\n"); break; } } else { break; } } else { break; } } return ret; }