main.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. // STM32F100 and SI4032 RTTY transmitter
  2. // released under GPL v.2 by anonymous developer
  3. // enjoy and have a nice day
  4. // ver 1.5a
  5. #include <stm32f10x_gpio.h>
  6. #include <stm32f10x_tim.h>
  7. #include <stm32f10x_spi.h>
  8. #include <stm32f10x_tim.h>
  9. #include <stm32f10x_usart.h>
  10. #include <stm32f10x_adc.h>
  11. #include <stm32f10x_rcc.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <misc.h>
  16. #include "config.h"
  17. #include "delay.h"
  18. #include "f_rtty.h"
  19. #include "init.h"
  20. #include "radio.h"
  21. #include "ublox.h"
  22. #include "util.h"
  23. #include "satpredict.h"
  24. #include "morse.h"
  25. #define GREEN GPIO_Pin_7 // Inverted
  26. #define RED GPIO_Pin_8 // Think this is inverted too
  27. enum { STARTUP, RTTY, MORSE };
  28. volatile int current_mode = STARTUP;
  29. // Telemetry Data to Transmit
  30. unsigned int send_count;
  31. int voltage;
  32. int8_t si4032_temperature;
  33. GPSEntry gpsData;
  34. float tx_freq = TRANSMIT_FREQUENCY;
  35. char callsign[15] = {CALLSIGN};
  36. uint16_t CRC_rtty = 0x12ab;
  37. char buf_rtty[200];
  38. // Volatile Variables, used within interrupts.
  39. volatile int adc_bottom = 2000;
  40. volatile char flaga = 0; // GPS Status Flags
  41. volatile int led_enabled = 1; // Flag to disable LEDs at altitude.
  42. volatile unsigned char pun = 0;
  43. volatile unsigned int cun = 10;
  44. volatile unsigned char tx_on = 0;
  45. volatile unsigned int tx_on_delay;
  46. volatile unsigned char tx_enable = 0;
  47. rttyStates send_rtty_status = rttyZero;
  48. volatile char *tx_buffer;
  49. volatile uint16_t button_pressed = 0;
  50. volatile uint8_t disable_armed = 0;
  51. void collect_telemetry_data (void);
  52. void send_rtty_packet (void);
  53. uint16_t gps_CRC16_checksum (char *string);
  54. void morse_beacon (void);
  55. //
  56. // GPS data processing
  57. void USART1_IRQHandler (void)
  58. {
  59. if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  60. ublox_handle_incoming_byte((uint8_t) USART_ReceiveData(USART1));
  61. else
  62. //if (USART_GetITStatus(USART1, USART_IT_ORE) != RESET)
  63. // USART_ReceiveData(USART1);
  64. //else /* wut */
  65. USART_ReceiveData(USART1);
  66. }
  67. //
  68. // Symbol Timing Interrupt
  69. // In here symbol transmission occurs.
  70. void TIM2_IRQHandler(void)
  71. {
  72. if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  73. {
  74. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  75. //
  76. if (ALLOW_DISABLE_BY_BUTTON)
  77. {
  78. if (ADCVal[1] > adc_bottom)
  79. {
  80. button_pressed++;
  81. if (button_pressed > (BAUD_RATE / 3))
  82. {
  83. disable_armed = 1;
  84. GPIO_SetBits(GPIOB, RED);
  85. }
  86. }
  87. else
  88. {
  89. if (disable_armed) GPIO_SetBits(GPIOA, GPIO_Pin_12);
  90. button_pressed = 0;
  91. }
  92. if (button_pressed == 0)
  93. adc_bottom = ADCVal[1] * 1.1; // dynamical reference for power down level
  94. }
  95. //
  96. if (tx_on)
  97. {
  98. if (current_mode == RTTY)
  99. {
  100. send_rtty_status = send_rtty((char *) tx_buffer);
  101. if (!disable_armed)
  102. {
  103. if (send_rtty_status == rttyEnd)
  104. {
  105. if (led_enabled) GPIO_ResetBits(GPIOB, RED);
  106. if (*(++tx_buffer) == 0)
  107. {
  108. tx_on = 0;
  109. // Reset the TX Delay counter, which is decremented at the symbol rate.
  110. tx_on_delay = TX_DELAY / (1000/BAUD_RATE);
  111. tx_enable = 0;
  112. radio_disable_tx();
  113. }
  114. }
  115. if (send_rtty_status == rttyOne)
  116. {
  117. radio_rw_register(0x73, RTTY_DEVIATION, 1);
  118. if (led_enabled) GPIO_SetBits(GPIOB, RED);
  119. }
  120. if (send_rtty_status == rttyZero)
  121. {
  122. radio_rw_register(0x73, 0x00, 1);
  123. if (led_enabled) GPIO_ResetBits(GPIOB, RED);
  124. }
  125. }
  126. }
  127. } /* C should not look like LISP... */
  128. // Delay between Transmissions Logic.
  129. // tx_on_delay is set at the end of a RTTY transmission above, and counts down
  130. // at the interrupt rate. When it hits zero, we set tx_enable to 1, which allows
  131. // the main loop to continue.
  132. if (!tx_on && --tx_on_delay == 0)
  133. {
  134. tx_enable = 1;
  135. tx_on_delay--;
  136. }
  137. // Green LED Blinking Logic
  138. if (--cun == 0)
  139. {
  140. if (pun)
  141. {
  142. // Clear Green LED.
  143. if (led_enabled) GPIO_SetBits(GPIOB, GREEN);
  144. pun = 0;
  145. }
  146. else
  147. {
  148. // If we have GPS lock, set LED
  149. if (flaga & 0x80)
  150. if (led_enabled) GPIO_ResetBits(GPIOB, GREEN);
  151. pun = 1;
  152. }
  153. // Wait 200 symbols.
  154. cun = 200;
  155. }
  156. }
  157. }
  158. int main (void)
  159. {
  160. RCC_Conf();
  161. NVIC_Conf();
  162. init_port();
  163. init_timer (BAUD_RATE);
  164. delay_init();
  165. ublox_init();
  166. GPIO_SetBits (GPIOB, RED);
  167. GPIO_SetBits (GPIOB, GREEN); // NOTE - Green LED is inverted. (Reset to activate, Set to deactivate)
  168. USART_SendData (USART3, 0xc); /* ? */
  169. radio_soft_reset();
  170. radio_set_tx_frequency (tx_freq); // setting RTTY TX frequency
  171. radio_rw_register (0x6D, 00 | (TX_POWER & 0x0007), 1); // setting TX power
  172. radio_rw_register (0x71, 0x00, 1); // initial RTTY modulation
  173. radio_rw_register (0x13, 0x00, 1); // Was 0xF0(?) Temperature Value Offset
  174. radio_rw_register (0x12, 0x20, 1); // Temperature Sensor Calibration
  175. radio_rw_register (0x0f, 0x80, 1); // ADC configuration
  176. tx_buffer = buf_rtty;
  177. tx_on = 0;
  178. tx_enable = 1;
  179. // Why do we have to do this again?
  180. spi_init();
  181. radio_set_tx_frequency(tx_freq);
  182. radio_rw_register(0x71, 0x00, 1);
  183. init_timer(BAUD_RATE);
  184. radio_enable_tx();
  185. //
  186. int pass = 0;
  187. while (1)
  188. {
  189. if (tx_on == 0 && tx_enable)
  190. switch (current_mode)
  191. {
  192. case STARTUP:
  193. collect_telemetry_data();
  194. send_rtty_packet();
  195. current_mode = RTTY;
  196. break;
  197. case RTTY:
  198. radio_disable_tx();
  199. sat_update();
  200. tx_freq = TRANSMIT_FREQUENCY;
  201. #if 0
  202. for (int ind = 0; ind < numsats; ind++)
  203. if ((satstatus[ind].elevation > HORIZON)
  204. || (satstatus[ind].elevation > 0) && ((gpsData.alt_raw/1000) >= FLYING))
  205. tx_freq = satdata[ind].uplink;
  206. radio_set_tx_frequency(tx_freq); /* hopefully this is doable.. */
  207. radio_rw_register(0x71, 0x00, 1);
  208. current_mode = MORSE;
  209. #endif
  210. current_mode = STARTUP;
  211. break;
  212. case MORSE:
  213. morse_beacon ();
  214. current_mode = STARTUP;
  215. }
  216. else
  217. {
  218. NVIC_SystemLPConfig(NVIC_LP_SEVONPEND, DISABLE);
  219. __WFI();
  220. }
  221. pass++;
  222. }
  223. }
  224. void collect_telemetry_data (void)
  225. {
  226. send_count++;
  227. si4032_temperature = radio_read_temperature();
  228. voltage = ADCVal[0] * 600 / 4096;
  229. ublox_get_last_data(&gpsData);
  230. if (gpsData.fix >= 3)
  231. {
  232. flaga |= 0x80;
  233. if ((gpsData.alt_raw/1000) > 1000) /* Disable LEDs if altitude is > 1000m */
  234. led_enabled = 0; /* not living in Armidale again anyway.. */
  235. else
  236. led_enabled = 1;
  237. }
  238. else
  239. {
  240. flaga &= ~0x80; // No GPS fix.
  241. led_enabled = 1; // Enable LEDs when there is no GPS fix (i.e. during startup)
  242. gpsData.lat_raw = 0; // Null out lat / lon data to avoid spamming invalid positions
  243. gpsData.lon_raw = 0;
  244. }
  245. }
  246. void send_rtty_packet (void)
  247. {
  248. uint8_t lat_d = (uint8_t) abs(gpsData.lat_raw / 10000000);
  249. uint32_t lat_fl = (uint32_t) abs(abs(gpsData.lat_raw) - lat_d * 10000000) / 1000;
  250. uint8_t lon_d = (uint8_t) abs(gpsData.lon_raw / 10000000);
  251. uint32_t lon_fl = (uint32_t) abs(abs(gpsData.lon_raw) - lon_d * 10000000) / 1000;
  252. uint8_t speed_kph = (uint8_t)((float)gpsData.speed_raw*0.0036);
  253. sprintf(buf_rtty, "$$$$%s,%d,%02u:%02u:%02u,%s%d.%05ld,%s%d.%05ld,%ld,%d,%d,%d,%d",
  254. callsign, send_count, gpsData.hours, gpsData.minutes, gpsData.seconds,
  255. gpsData.lat_raw < 0 ? "-" : "", lat_d, lat_fl, gpsData.lon_raw < 0 ? "-" : "", lon_d, lon_fl,
  256. (gpsData.alt_raw / 1000), speed_kph, gpsData.sats_raw, voltage*10, si4032_temperature );
  257. CRC_rtty = string_CRC16_checksum(buf_rtty + 9); /* sensitive to the $$$$ stuff */
  258. sprintf(buf_rtty, "%s*%04X\n\n", buf_rtty, CRC_rtty & 0xffff);
  259. // if on the non-satellite frequency indicate what's being tx'd too
  260. // I hate the temporary RAM usage here.. :|
  261. if (tx_freq == TRANSMIT_FREQUENCY)
  262. for (int i = 0; i < numsats; i++)
  263. if ((satstatus[i].elevation > HORIZON)
  264. || ((satstatus[i].elevation > 0) && ((gpsData.alt_raw/1000) >= FLYING)))
  265. sprintf (buf_rtty, "%sSAT %s d=%f\n", buf_rtty, satdata[i].name, satstatus[i].dopplerhz);
  266. //
  267. tx_buffer = buf_rtty;
  268. start_bits = RTTY_PRE_START_BITS;
  269. radio_enable_tx();
  270. tx_on = 1;
  271. return;
  272. }
  273. void morse_beacon (void)
  274. {
  275. /* just testing satellite repeaters atm */
  276. send_morse ("EEEEE VK2CJB VK2CJB +");
  277. }