Files
stm32samples/G4:G431/CORDIC/Readme.md
Edward Emelianov 8200366090 add astro-tests
2026-09-08 22:42:06 +03:00

242 lines
10 KiB
Markdown

# 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 = <func>` | Test CORDIC function: `sincos`, `sin`, `cos`, `atan`, `sqrt`, `log`. Prints time in us. |
| `testm = <func>` | Test `math.h` function: `sin`, `cos`, `atan`, `sqrt`, `log`. Prints time in us. |
| `sincos = <angle>` | Compute sin/cos for given angle (degrees) using both `math.h` and CORDIC, print results. |
| `testastro = <func>` | 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.