ublox(4337).c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * ublox.c
  3. *
  4. * Created on: Oct 28, 2017
  5. * Author: Milosz Iskrzynski SQ6NTI
  6. */
  7. #include "ublox.h"
  8. ubxGPSData currentGPSData;
  9. ubxPacket recentCfgResponse;
  10. int recentCfgResponseValid;
  11. UART_HandleTypeDef *gpsUart;
  12. void ubxInit(UART_HandleTypeDef *uart) {
  13. gpsUart = uart;
  14. /* Try to reset GPS at modified baud rate first (38400) */
  15. ubxMessage cfgRstMsg = {
  16. .cfgrst = {
  17. .navBbrMask = 0xffff,
  18. .resetMode = 1,
  19. .reserved1 = 0
  20. }
  21. };
  22. //ubxSendPacket(UBX_CFG, UBX_CFG_RST, sizeof(ubxCfgRst), cfgRstMsg);
  23. HAL_Delay(800); /* Wait for reset (how long does the reset take?) */
  24. /* Switch to default (9600) and try to reset GPS again in case previous try failed */
  25. HAL_UART_DMAStop(gpsUart);
  26. UART_ReInit(gpsUart, 9600);
  27. //ubxSendPacket(UBX_CFG, UBX_CFG_RST, sizeof(ubxCfgRst), cfgRstMsg);
  28. HAL_Delay(800); /* wait for reset (how long does the reset take?) */
  29. /* Configure port for 38400 baud rate and switch to the new settings */
  30. ubxMessage cfgPrtMsg = {
  31. .cfgprt = {
  32. .portID = 1,
  33. .reserved1 = 0,
  34. .txReady = 0,
  35. .mode = 0b00100011000000,
  36. .baudRate = 38400,
  37. .inProtoMask = 1,
  38. .outProtoMask = 1,
  39. .reserved2 = {0,0}
  40. }
  41. };
  42. ubxSendPacket(UBX_CFG, UBX_CFG_PRT, sizeof(ubxCfgPrt), cfgPrtMsg);
  43. UART_ReInit(gpsUart, 38400);
  44. HAL_Delay(100); /* wait until ublox re-config is done (what should be the exact time?) */
  45. //ubxSendPacket(UBX_CFG, UBX_CFG_PRT, sizeof(ubxCfgPrt), cfgPrtMsg);
  46. /* Configure NAV-POSLLH outgoing messages */
  47. ubxMessage cfgMsgMsg = {
  48. .cfgmsg = {
  49. .msgClass = 0x01,
  50. .msgID = 0x02,
  51. .rate = 5
  52. }
  53. };
  54. do {
  55. ubxSendPacket(UBX_CFG, UBX_CFG_MSG, sizeof(ubxCfgMsg), cfgMsgMsg);
  56. } while (!ubxResponseWait(20));
  57. /* Configure NAV-STATUS outgoing messages */
  58. cfgMsgMsg.cfgmsg.msgID = 0x03;
  59. do {
  60. ubxSendPacket(UBX_CFG, UBX_CFG_MSG, sizeof(ubxCfgMsg), cfgMsgMsg);
  61. } while (!ubxResponseWait(20));
  62. }
  63. void ubxRxByte(uint8_t data) {
  64. static uint8_t dataPos = 0;
  65. static uint8_t ubxSync = 0;
  66. static uint8_t ubxHeaderReady = 0;
  67. static uint16_t msgPos = 0;
  68. static uint16_t lengthWithHeader = 0;
  69. static ubxPacket packet;
  70. static const ubxPacket EmptyPacket;
  71. if (!ubxSync) {
  72. if (dataPos == 0 && data == UBX_SYNC1) { /* Check fist sync byte of UBX Packet */
  73. packet.header.syncChar1 = UBX_SYNC1;
  74. dataPos = 1;
  75. } else if (dataPos == 1 && data == UBX_SYNC2) { /* Check second sync byte of UBX Packet */
  76. packet.header.syncChar2 = UBX_SYNC2;
  77. ubxSync = 1;
  78. dataPos = 2;
  79. } else { /* Reset state if sync bytes not received in the above sequence */
  80. dataPos = 0;
  81. }
  82. } else { /* Synchronization is now assumed */
  83. if (!ubxHeaderReady) {
  84. if (dataPos == 2) {
  85. packet.header.messageClass = data;
  86. } else if (dataPos == 3) {
  87. packet.header.messageId = data;
  88. } else if (dataPos == 4) {
  89. packet.header.payloadLength = data;
  90. } else if (dataPos == 5) {
  91. packet.header.payloadLength += data << 8; /* multiple of 256) */
  92. lengthWithHeader = sizeof(ubxHeader) + packet.header.payloadLength;
  93. ubxHeaderReady = 1;
  94. }
  95. } else { /* Header is now ready, start reading payload and checksum */
  96. if (dataPos < lengthWithHeader) {
  97. ((uint8_t *)&packet.message)[msgPos] = data;
  98. msgPos++;
  99. } else if (dataPos == lengthWithHeader) { /* read ck_a */
  100. packet.checksum.ck_a = data;
  101. } else if (dataPos == lengthWithHeader+1) { /* read ck_b */
  102. packet.checksum.ck_b = data;
  103. } else { /* Packet is now ready for further processing */
  104. /* Static status cleanup */
  105. dataPos = 0;
  106. ubxSync = 0;
  107. ubxHeaderReady = 0;
  108. msgPos = 0;
  109. lengthWithHeader = 0;
  110. ubxProcessPacket(&packet);
  111. packet = EmptyPacket;
  112. }
  113. }
  114. dataPos++;
  115. }
  116. }
  117. void ubxProcessPacket(const ubxPacket *packet) {
  118. /* Checksum validation */
  119. ubxChecksum checksum = ubxCalcChecksum(packet);
  120. if (checksum.ck_a != packet->checksum.ck_a || checksum.ck_b != packet->checksum.ck_b) {
  121. return;
  122. }
  123. /* Select action based on message class and ID */
  124. if (packet->header.messageClass == UBX_ACK) {
  125. recentCfgResponse = *packet;
  126. recentCfgResponseValid = 1;
  127. } else if (packet->header.messageClass == UBX_NAV) {
  128. if (packet->header.messageId == UBX_NAV_POSLLH) {
  129. currentGPSData.lat = packet->message.navposllh.lat;
  130. currentGPSData.lon = packet->message.navposllh.lon;
  131. currentGPSData.alt = packet->message.navposllh.hMSL;
  132. } else if (packet->header.messageId == UBX_NAV_TIMEUTC) {
  133. currentGPSData.year = packet->message.navtimeutc.year;
  134. currentGPSData.month = packet->message.navtimeutc.month;
  135. currentGPSData.day = packet->message.navtimeutc.day;
  136. currentGPSData.hour = packet->message.navtimeutc.hour;
  137. currentGPSData.minute = packet->message.navtimeutc.min;
  138. currentGPSData.second = packet->message.navtimeutc.sec;
  139. } else if (packet->header.messageId == UBX_NAV_STATUS) {
  140. currentGPSData.fix = packet->message.navstatus.flags & 1;
  141. }
  142. }
  143. }
  144. int ubxResponseWait(int timeout) {
  145. while (!recentCfgResponseValid) {
  146. HAL_Delay(10);
  147. if (timeout > 0) {
  148. timeout--;
  149. } else {
  150. return 0;
  151. }
  152. }
  153. if (recentCfgResponse.header.messageId == UBX_ACK_ACK) {
  154. return 1;
  155. }
  156. return 0;
  157. }
  158. void ubxSendPacket(uint8_t messageClass, uint8_t messageId, uint16_t payloadLength, ubxMessage message) {
  159. ubxPacket packet = {
  160. .header = {
  161. .syncChar1 = UBX_SYNC1,
  162. .syncChar2 = UBX_SYNC2,
  163. .messageClass = messageClass,
  164. .messageId = messageId,
  165. .payloadLength = payloadLength
  166. },
  167. .message = message,
  168. .checksum = {0,0}
  169. };
  170. packet.checksum = ubxCalcChecksum(&packet);
  171. if (packet.header.messageClass == UBX_CFG) {
  172. /* When sending CFG message, we expect ACK or NAK in return. Invalidate previous CFG esponse. */
  173. recentCfgResponseValid = 0;
  174. }
  175. ubxTxPacket(packet);
  176. }
  177. void ubxTxPacket(ubxPacket packet) {
  178. UART_TxStart(gpsUart);
  179. while (HAL_UART_Transmit_DMA(gpsUart, (void*)&packet.header, sizeof(ubxHeader)) == HAL_BUSY);
  180. while (!UART_TxFinished(gpsUart));
  181. UART_TxStart(gpsUart);
  182. while (HAL_UART_Transmit_DMA(gpsUart, (void*)&packet.message, packet.header.payloadLength) == HAL_BUSY);
  183. while (!UART_TxFinished(gpsUart));
  184. UART_TxStart(gpsUart);
  185. while (HAL_UART_Transmit_DMA(gpsUart, (void*)&packet.checksum, sizeof(ubxChecksum)) == HAL_BUSY);
  186. while (!UART_TxFinished(gpsUart));
  187. }
  188. ubxChecksum ubxCalcChecksum(const ubxPacket *packet) {
  189. uint8_t *message = (uint8_t *)&packet->message;
  190. ubxChecksum checksum = {0, 0};
  191. uint8_t i;
  192. checksum.ck_a += packet->header.messageClass;
  193. checksum.ck_b += checksum.ck_a;
  194. checksum.ck_a += packet->header.messageId;
  195. checksum.ck_b += checksum.ck_a;
  196. checksum.ck_a += packet->header.payloadLength & 0xff;
  197. checksum.ck_b += checksum.ck_a;
  198. checksum.ck_a += packet->header.payloadLength >> 8;
  199. checksum.ck_b += checksum.ck_a;
  200. for (i=0; i < packet->header.payloadLength; i++){
  201. checksum.ck_a += message[i];
  202. checksum.ck_b += checksum.ck_a;
  203. }
  204. return checksum;
  205. }
  206. ubxGPSData ubxLastGPSData() {
  207. uint32_t prim;
  208. ubxGPSData gpsData;
  209. /* Get PRIMASK (current interrupt status) and disable global interrupts to preserve data integrity */
  210. prim = __get_PRIMASK();
  211. __disable_irq();
  212. gpsData = currentGPSData;
  213. /* Re-enable global interrupts, but only if PRIMASK register not set */
  214. if (!prim) {
  215. __enable_irq();
  216. }
  217. return gpsData;
  218. }