# STM32 Astronomy & CORDIC Test Project ## Introduction This project is designed for **STM32G4** microcontrollers (specifically the STM32G431) and provides a framework for: - **Astronomical coordinate transformations** (Alt-Az vs HA-Dec, RA/HA, Local Sidereal Time). - **Atmospheric refraction** modelling using a single-precision adaptation of SOFA/ERFA algorithms. - **Performance comparison** between standard `math.h` functions and the hardware-accelerated **CORDIC** unit built into the STM32G4. - **Interactive control** via a serial (UART) command interface. - **Precise timing** measurements using a 32-bit timer. All calculations are performed in **single-precision floating-point** for speed on microcontrollers without hardware double-precision support. --- ## Hardware Platform - **MCU**: STM32G431 (or any STM32G4 with CORDIC). - **Clock**: HSE oscillator, system frequency defined by `SysFreq` (usually 170 MHz). - **GPIO**: - **PC6** - LED (active high). - **PC13** - User button (pull-down, pressed = high). - **USART1**: - **PA9** - TX (alternate function 7). - **PA10** - RX (alternate function 7). - **Timers**: - **SysTick** - 1-ms system tick (`Tms`). - **TIM2** - 32-bit counter running at 1-MHz for microsecond measurements. --- ## Building and Flashing The project is intended for use with **GCC ARM** toolchain. Key build definitions: - `SysFreq` - system clock frequency in Hz (e.g., 170000000). - `BUILD_NUMBER` and `BUILD_DATE` are defined in `version.inc` (generated by `make`). Flashing can be done via SWD using st-link (`make flash`), via DFU (`make dfuboot`) or via USART1 bootloader (`make boot`). --- ## Software Architecture The system runs an infinite loop in `main()` that: - Services the UART (receiving and sending data). - Parses incoming commands via `parse_cmd()`. - Blinks the LED every 500 ms. - Detects button presses and measures press/release duration using TIM2. --- ## Module Descriptions ### 1. `hardware.c/h` - Low-level initialisation - `gpio_setup()`: configures GPIOs, enables SysTick (1 ms interrupt), and initialises TIM2 for microsecond counting. - Provides macros for LED and key handling: - `LED_ON()`, `LED_OFF()`, `LED_TOGG()` - `KEY_PRESSED()` - returns true if PC13 is high. - `timer_start()`, `timer_stop()`, `timer_read()` - control TIM2 for precise time measurements. ### 2. `usart.c/h` - UART1 with DMA and ring buffers - Uses **circular DMA** for RX and **normal DMA** for TX. - RX buffer size: 256 bytes (DMA) + 512 bytes (ring buffer). - TX buffer size: 512 bytes (ring buffer) + 256 bytes (DMA). - Interrupts: - USART1 interrupt - detects end-of-line (`\n`) and triggers line processing. - DMA1 Channel 1 (RX) - handles receive error (buffer overflow). - DMA1 Channel 2 (TX) - signals transmit completion. - Functions: - `usart_setup(uint32_t baud)` - initialises UART at the given baud rate. - `usart_sendstr(const char*)` - queues a string for transmission. - `usart_getline()` - returns a pointer to a null-terminated buffer containing one line (ends with `\n`), or `NULL` if no complete line. - `usart_process()` - must be called frequently to feed the TX buffer and move RX data from DMA to the ring buffer; returns status flags. ### 3. `commproto.cpp` - Command protocol - Parses commands of the form: ``` command [args] [= value] ``` - Built-in commands and variables (see **Usage** below). - Uses a **hash table** (compile-time hashing) to dispatch commands efficiently. - Supports **getter** and **setter** for floating-point variables (az, dec, ha, ra, zd, humid, press, temp). - Command results are sent back via the UART send function. - Error codes are defined in `commproto.h`. ### 4. `astro.c/h` - Astronomical calculations All angles are in **degrees** unless otherwise noted. - **Time**: - `MJD_from_unix(uint32_t t)` - converts Unix time (seconds since 1970-01-01) to Modified Julian Date (MJD). - `LST_from_unix(uint32_t t)` - computes Local Sidereal Time (in hours) for the observer's longitude (`long_hrs`). - **Coordinate transformations**: - `altaz_to_hadec()` - convert Alt-Az to HA-Dec. - `hadec_to_altaz()` - convert HA-Dec to Alt-Az. - `ha_to_ra()` and `ra_to_ha()` - convert between Hour Angle and Right Ascension given LST. - **Refraction** (single-precision adaptation of ERFA `eraRefco`): - `refco_f32(float P, float T, float RH, float wavelength, float *refa, float *refb)` - computes A and B coefficients for the refraction model: `dz = A*tan(z) + B*tan(z)^3` (z = zenith distance). - `refraction(float P, float T, float RH, float zd)` - returns the refraction correction in degrees. - The observer's **latitude** and **longitude** are fixed in the code (`lat_rad` and `long_hrs`). They may be changed by editing `astro.c`. ### 5. `cordic.c/h` - Hardware CORDIC wrappers - Interfaces with the STM32G4 CORDIC coprocessor. - Functions: - `cordic_sincos(float angle, float *sin, float *cos)` - computes sine and cosine in one call. - `cordic_sin(float angle)`, `cordic_cos(float angle)` - individual functions. - `cordic_atan(float x)` - returns atan(x), x in [-1,1]. - `cordic_sqrt(float x)` - returns sqrt(x) for x > 0. - `cordic_log(float x)` - returns natural logarithm of x (x > 0). - **Precision**: Q1.31 fixed-point (32-bit) with 5 iterations (`CORDIC_CSR_PRECISION = 5`). - Input scaling and normalisation are handled inside each function. ### 6. `strfunc.c/h` - String utilities - Number formatting: - `u2str()`, `i2str()`, `uhex2str()` - convert integers to strings. - `float2str(float x, uint8_t prec)` - convert float to a compact string with optional scientific notation. - Number parsing: - `getnum()`, `getint()`, `getfloat()` - parse numbers (decimal, hex, binary, signed, floating with exponent). - `omit_spaces()` - skip leading whitespace. ### 7. `ringbuffer.c/h` - Circular buffer - Generic ring buffer for arbitrary data. - Functions: - `RB_write()`, `RB_read()`, `RB_readto()` (read until a delimiter), `RB_hasbyte()`, `RB_datalen()`, `RB_clearbuf()`. ### 8. `test.c/h` - Performance tests - Runs a fixed number of iterations (`N_TESTS = 1000`) on random data. - Measures execution time using TIM2 (microseconds). - Tests available: - `math` functions: `sinf`, `cosf`, `atanf`, `sqrtf`, `logf`. - `CORDIC` functions: `sincos`, `sin`, `cos`, `atan`, `sqrt`, `log`. - **Astronomy** tests: - Coordinate transformations (Alt-Az vs HA-Dec) - measures time per conversion. - Refraction cycle (ha-dec to alt-az, apply refraction and convert back) - includes `refraction()`. - LST calculation - measures time per LST computation. --- ## Usage: UART Commands Connect to the USART1 (default baud rate **115200**, 8N1) using a terminal program. The device echoes responses to commands. General syntax: ``` command [args] [= value] ``` - Without `= value`, the command acts as a **getter** (prints current value) or command that don't needs argument. - With `= value`, it acts as a **setter**. All floating-point values are printed with 7 decimal places. ### Available Commands | Command | Description | |---------|-------------| | `help` | Show this help message. | | `testtimer` | Test the microsecond timer for 1 second (prints elapsed us). | | `testc = ` | Test CORDIC function: `sincos`, `sin`, `cos`, `atan`, `sqrt`, `log`. Prints time in us. | | `testm = ` | Test `math.h` function: `sin`, `cos`, `atan`, `sqrt`, `log`. Prints time in us. | | `sincos = ` | Compute sin/cos for given angle (degrees) using both `math.h` and CORDIC, print results. | | `testastro = ` | Test astronomy functions: `coords` (transform cycle), `lst` (LST calculation), `refr` (refraction cycle). Prints time in us and ms. | | `sets [= 0/1]` | Choose sine/cos implementation: `0` = `math.h`, `1` = CORDIC. | | `time [= unix_sec]` | Show current Unix time, MJD, and LST. If `= unix_sec` is given, sets the system time. | | `az [= value]` | Azimuth (degrees, -180..180). | | `dec [= value]` | Declination (degrees, -90..90). | | `ha [= value]` | Hour Angle (degrees, -180..180). | | `ra [= value]` | Right Ascension (degrees, 0..360). | | `zd [= value]` | Zenith Distance (degrees, 0..90). | | `humid [= value]` | Relative humidity (0..1). | | `press [= value]` | Atmospheric pressure (hPa, 0..1200). | | `temp [= value]` | Temperature (degC, -273.15..100). | | `hara = 0/1` | Convert HA to RA (`0`) or RA to HA (`1`) using current LST. Updates the corresponding variable. | | `azhd = 0/1` | Convert Alt-Az to HA-Dec (`0`) or HA-Dec to Alt-Az (`1`). Updates relevant variables (az, zd or ha, dec, ra). | | `refr` | Compute refraction (arcseconds) for current `zd`, pressure, temperature, humidity. Also prints A/B coefficients. | **Note**: The `azhd` and `hara` commands automatically use the current system time (from the last `time` setter) to compute LST. --- ## Testing and Performance The test commands (`testc`, `testm`, `testastro`) measure execution time over 1000 iterations on random input data. This allows you to compare the speed of hardware CORDIC against software `math.h` and evaluate the overall efficiency of the astronomical pipeline. Example outputs (typical for STM32G4 @ 170 MHz): ``` testc = sincos TIMEus=425 ``` ``` testm = sin TIMEus=884 ``` ``` testastro = coords TIMEus=159680 TIMEms=159 ``` These numbers help in optimising real-time applications such as telescope control. --- ## Notes and Customisation - **Observer coordinates**: The latitude (43.6535278deg) and longitude (41.44143375deg) are hard-coded in `astro.c` as `lat_rad` and `long_hrs`. Modify these for your location. - **CORDIC precision**: The number of iterations is set to 5 (`CORDIC_CSR_DEF`). You can increase it for better accuracy at the cost of speed. - **Refraction model**: The model works best for zenith distances up to ~80deg. It uses a wavelength of 0.55um (optical) by default. - **Baud rate**: Default is 115200. Change the argument to `usart_setup()` in `main()` if needed. - **DMA buffers**: Sizes are defined in `usart.h`. Adjust if you experience overruns. --- ## License This project is released under the **GNU General Public License v3**. See the header of each source file for details.