ublox(4753).c 7.3 KB

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