#pragma once

#include <Arduino.h>

//
//  Project-wide hardware and behaviour configuration.
//
//  Board : NUCLEO-F042K6  (STM32F042K6T6, LQFP32, board MB1180)
//          32 KB flash / 6 KB RAM
//  Sensor: 2x GY-63 breakout carrying a MS5611-01BA03
//          one on I2C1, one on SPI1
//
//  Pin facts below are taken from ST UM1956 "STM32 Nucleo-32 boards (MB1180)"
//  Table 10 + the MB1180 C.2 schematic, cross-checked against the STM32duino
//  variant files for NUCLEO_F042K6.
//

// ---------------------------------------------------------------------------
//  I2C sensor  ("baro0")
// ---------------------------------------------------------------------------
//  STM32duino default Wire pins for this variant:
//      PIN_WIRE_SDA = PB7  (Arduino D4, routed to the A4 header pad via SB18)
//      PIN_WIRE_SCL = PB6  (Arduino D5, routed to the A5 header pad via SB16)
//  Both are the STM32duino defaults, so plain Wire.begin() selects them and no
//  explicit setSDA()/setSCL() call is required.
//
//  MS5611 I2C address is 1110 11Cx where C is the COMPLEMENT of the CSB pin
//  (datasheet p.12), therefore:
//      CSB tied to GND -> 0x77
//      CSB tied to VCC -> 0x76
//  Change this if the GY-63 CSB pad is strapped high.
#define BARO_I2C_ADDRESS        0x77

// ---------------------------------------------------------------------------
//  SPI sensor  ("baro1")
// ---------------------------------------------------------------------------
//  SPI1 MUST stay on the PB3/PB4/PB5 group on this board.
//
//  The alternative SPI1 group (PA5 SCK / PA6 MISO / PA7 MOSI) is NOT usable
//  here: with the factory-default solder bridges SB16 and SB18 closed, PA6 is
//  tied to the same net as PB6 (I2C SCL) and PA5 is tied to the same net as
//  PB7 (I2C SDA). Driving SPI on PA5/PA6 while I2C runs on PB6/PB7 would put
//  two peripherals on one net. See UM1956 Table 8 (SB16/SB18).
//
//      SCK  = PB3  (Arduino D13)   <- also the on-board user LED LD3, see below
//      MISO = PB4  (Arduino D12)   <- connect to sensor SDO
//      MOSI = PB5  (Arduino D11)   <- connect to sensor SDI
//  These three are the STM32duino defaults (core falls back to Arduino pin
//  numbers 13/12/11), so plain SPI.begin() selects them.
#define BARO_SPI_CS_PIN         PA11    // Arduino D10, core default PIN_SPI_SS

//  MS5611 accepts SPI mode 0 and mode 3, up to 20 MHz (datasheet p.5/p.6).
//  The library hardcodes mode 0; 1 MHz is its default and is plenty here.
#define BARO_SPI_CLOCK_HZ       1000000UL

// ---------------------------------------------------------------------------
//  Error indicator LEDs - one per sensor
// ---------------------------------------------------------------------------
//  IMPORTANT: the NUCLEO-F042K6 has exactly ONE user-controllable LED, and it
//  is unusable for this project:
//
//    LD1 (COM, tricolor) - driven by the ST-LINK MCU, not by the target
//    LD2 (PWR, red)      - hardwired to the power rail, not by the target
//    LD3 (user, green)   - on PB3 via SB15 + R23, and PB3 is our SPI1 SCK
//
//  So both indicators are external LEDs (LED + ~510R to GND) on free GPIOs.
//  PB0/PB1 are plain GPIO on this board and collide with nothing we use.
#define LED_BARO_I2C_PIN        PB0     // Arduino D3 - error LED for the I2C sensor
#define LED_BARO_SPI_PIN        PB1     // Arduino D6 - error LED for the SPI sensor

//  How long an LED stays lit after an error is detected.
#define LED_ERROR_HOLD_MS       1000UL

// ---------------------------------------------------------------------------
//  UART
// ---------------------------------------------------------------------------
//  `Serial` on this variant is USART2 (SERIAL_UART_INSTANCE 2) on PA2/PA15,
//  which is wired to the ST-LINK Virtual COM Port. No extra wiring needed.
#define UART_BAUD               115200UL

//  Measurement report rate: 10 Hz.
#define REPORT_PERIOD_MS        100UL

// ---------------------------------------------------------------------------
//  Acquisition
// ---------------------------------------------------------------------------
//  The driver's read() busy-waits through two conversions, so a poll of both
//  sensors is the loop period, and the report deadline can only be evaluated
//  on that grid. Keeping the cycle short keeps the 10 Hz output jitter small:
//
//      OSR_STANDARD   (1024) 2.28 ms/conv -> ~5 ms/sensor  -> ~11 ms cycle
//      OSR_ULTRA_HIGH (4096) 9.04 ms/conv -> ~19 ms/sensor -> ~37 ms cycle
//
//  Conversion times are the datasheet p.3 maxima. OSR 1024 already resolves
//  well under a mbar, so it is the better trade here; raise it if resolution
//  matters more than tight report timing.
#define BARO_OVERSAMPLING       OSR_STANDARD

//  Retry interval for a sensor that failed to initialise.
#define BARO_INIT_RETRY_MS      2000UL

//  Consecutive failed polls after which the channel is torn down and taken
//  back through the full reset + PROM/CRC handshake. Covers a sensor that was
//  unplugged, browned out, or otherwise lost its calibration constants.
#define BARO_REINIT_AFTER_ERRORS 10

// ---------------------------------------------------------------------------
//  Validation limits
// ---------------------------------------------------------------------------
//  MS5611-01BA03 operating ranges (datasheet p.2/p.4).
#define BARO_PRESSURE_MIN_MBAR  10.0f
#define BARO_PRESSURE_MAX_MBAR  1200.0f
#define BARO_TEMP_MIN_C         (-40.0f)
#define BARO_TEMP_MAX_C         85.0f

//  A healthy MS5611 dithers by well under a mbar but never repeats a 24-bit
//  reading bit-for-bit many times running. Identical pressure AND temperature
//  this many polls in a row means the sensor stopped converting while still
//  answering on the bus.
#define BARO_STALE_LIMIT        32
