/src/main.c

https://github.com/AlexWongws/Firmware · C · 240 lines · 189 code · 51 blank · 0 comment · 24 complexity · 97244404f69b430b3381fb571b5a7129 MD5 · raw file

  1. #include <stdint.h>
  2. #include "main.h"
  3. #include "adc.h"
  4. #include "comio.h"
  5. #include "commhandler.h"
  6. #include "config.h"
  7. #include "fasttrig.h"
  8. #include "engine.h"
  9. #include "gyro.h"
  10. #include "pwm.h"
  11. #include "pins.h"
  12. #include "rc.h"
  13. #include "systick.h"
  14. #include "utils.h"
  15. #include "hw_config.h"
  16. #include "stm32f10x_tim.h"
  17. #define SETTLE_PAUSE 13
  18. static volatile int WatchDogCounter;
  19. static volatile int gotIMU = 0;
  20. void Periph_clock_enable(void)
  21. {
  22. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
  23. RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
  24. RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO |
  25. RCC_APB2Periph_ADC1 | RCC_APB2Periph_TIM1 |
  26. RCC_APB2Periph_TIM8, ENABLE);
  27. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5 | RCC_APB1Periph_TIM2 |
  28. RCC_APB1Periph_UART4 | RCC_APB1Periph_TIM3 |
  29. RCC_APB1Periph_TIM4, ENABLE);
  30. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  31. }
  32. void WatchDog(void)
  33. {
  34. if (WatchDogCounter++ > 1000)
  35. {
  36. LEDtoggle();
  37. PWMOff();
  38. DEBUG_PutChar('W');
  39. WatchDogCounter = 0;
  40. }
  41. }
  42. static float idlePerf;
  43. float GetIdlePerf(void)
  44. {
  45. return idlePerf;
  46. }
  47. void setup(void)
  48. {
  49. InitSysTick();
  50. Periph_clock_enable();
  51. GPIO_Config();
  52. __enable_irq();
  53. ComInit();
  54. print("\r\n\r\nEvvGC firmware starting up...\r\n");
  55. print("init motor PWM...\r\n");
  56. PWMConfig();
  57. for (int i = 0; i < 20; i++)
  58. {
  59. LEDtoggle();
  60. DEBUG_LEDtoggle();
  61. Delay_ms(100); //short blink
  62. }
  63. LEDoff();
  64. if (GetVCPConnectMode() != eVCPConnectReset)
  65. {
  66. print("\r\nUSB startup delay...\r\n");
  67. Delay_ms(3000);
  68. if (GetVCPConnectMode() == eVCPConnectData)
  69. {
  70. print("\r\n\r\nEvvGC firmware starting up, USB connected...\r\n");
  71. }
  72. }
  73. else
  74. {
  75. print("\r\nDelaying for usb/serial driver to settle\r\n");
  76. Delay_ms(3000);
  77. print("\r\n\r\nEvvGC firmware starting up, serial active...\r\n");
  78. }
  79. #ifdef __VERSION__
  80. print("gcc version " __VERSION__ "\r\n");
  81. print("EvvGC firmware V%s, build date " __DATE__ " "__TIME__" \r\n", __EV_VERSION);
  82. #endif
  83. if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  84. {
  85. print("running on external HSE clock, clock rate is %dMHz\r\n", SystemCoreClock / 1000000);
  86. }
  87. else
  88. {
  89. print("ERROR: running on internal HSI clock, clock rate is %dMHz\r\n", SystemCoreClock / 1000000);
  90. }
  91. print("init ADC...\r\n");
  92. ADC_Config();
  93. print("init MPU6050...\r\n");
  94. int imuRetries = 10;
  95. while ((imuRetries > 0) && MPU6050_Init())
  96. {
  97. print("init MPU6050 failed, retries left: %d...\r\n", --imuRetries);
  98. Blink();
  99. }
  100. if (!(gotIMU = imuRetries ? 1 : 0))
  101. {
  102. print("\r\nWARNING: MPU6050 init failed, entering configration mode only...\r\n\r\n");
  103. }
  104. print("loading config...\r\n");
  105. configLoad();
  106. if (gotIMU)
  107. {
  108. print("pausing for the gimbal to settle...\r\n");
  109. for (int i = 0; i < SETTLE_PAUSE; i++)
  110. {
  111. LEDtoggle();
  112. Delay_ms(1000);
  113. }
  114. print("calibrating MPU6050 at %ums...\r\n", millis());
  115. MPU6050_Gyro_calibration();
  116. print("Init Orientation\n\r");
  117. Init_Orientation();
  118. }
  119. print("init RC...\r\n");
  120. RC_Config();
  121. InitSinArray();
  122. int pendingCharacters = ComFlushInput();
  123. if (pendingCharacters > 0)
  124. {
  125. print("removed %d pending characters from communications input\r\n");
  126. }
  127. #if 0
  128. int c;
  129. while ((c = GetChar()) >= 0)
  130. {
  131. print("removed pending character %02X from communications input\r\n", c);
  132. }
  133. #endif
  134. print("entering main loop...\r\n");
  135. SysTickAttachCallback(WatchDog);
  136. }
  137. static int GetIdleMax(void)
  138. {
  139. unsigned int t0 = millis();
  140. while (millis() == t0)
  141. ;
  142. unsigned int lastTime = micros();
  143. int idleLoops = 0;
  144. __disable_irq();
  145. while (1)
  146. {
  147. idleLoops++;
  148. unsigned int currentTime = micros();
  149. unsigned int timePassed = currentTime - lastTime;
  150. if (timePassed >= 500U)
  151. {
  152. break;
  153. }
  154. }
  155. __enable_irq();
  156. int idleMax = 2 * idleLoops; // loops/ms
  157. idleLoops = 0;
  158. return idleMax;
  159. }
  160. int main(void)
  161. {
  162. setup();
  163. int idleMax = GetIdleMax();
  164. int idleLoops = 0;
  165. unsigned int lastTime = micros();
  166. while (1)
  167. {
  168. idleLoops++;
  169. unsigned int currentTime = micros();
  170. unsigned int timePassed = currentTime - lastTime;
  171. if (timePassed >= 2000)
  172. {
  173. idlePerf = idleLoops * 100.0 * 1000 / timePassed / idleMax; // perf in percent
  174. idleLoops = 0;
  175. if ((ConfigMode == 0) && gotIMU)
  176. {
  177. engineProcess(timePassed / 1000000.0);
  178. }
  179. else
  180. {
  181. PWMOff();
  182. Blink();
  183. }
  184. WatchDogCounter = 0;
  185. CommHandler();
  186. lastTime = currentTime;
  187. }
  188. }
  189. }