kopia lustrzana https://github.com/mikaelnousiainen/RS41ng
Require 3D fix from GPS by default to avoid transmitting invalid position information. Improve recovery from I2C bus errors, re-initialize BMP280 in case of errors. Allow disabling of LEDs based on altitude.
rodzic
d8f7584a99
commit
201b657c51
|
@ -110,7 +110,6 @@ Sensor driver code contributions are welcome!
|
||||||
|
|
||||||
### Planned features
|
### Planned features
|
||||||
|
|
||||||
* Continuous transmission mode for Horus 4FSK
|
|
||||||
* Configurable transmission frequencies and schedules based on location / altitude
|
* Configurable transmission frequencies and schedules based on location / altitude
|
||||||
* Support for more I²C sensors
|
* Support for more I²C sensors
|
||||||
* RTTY on both Si4032 (70 cm, non-standard shift) and Si5351 (HF + 2m) with configurable shift
|
* RTTY on both Si4032 (70 cm, non-standard shift) and Si5351 (HF + 2m) with configurable shift
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#include "drivers/bmp280/bmp280.h"
|
#include "drivers/bmp280/bmp280.h"
|
||||||
#include "bmp280_handler.h"
|
#include "bmp280_handler.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
bmp280 bmp280_dev;
|
bmp280 bmp280_dev;
|
||||||
|
|
||||||
|
static bool bmp280_initialization_required = true;
|
||||||
|
|
||||||
bool bmp280_handler_init()
|
bool bmp280_handler_init()
|
||||||
{
|
{
|
||||||
bmp280_dev.port = &DEFAULT_I2C_PORT;
|
bmp280_dev.port = &DEFAULT_I2C_PORT;
|
||||||
|
@ -17,12 +20,9 @@ bool bmp280_handler_init()
|
||||||
.standby = BMP280_STANDBY_250,
|
.standby = BMP280_STANDBY_250,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool bmp280_init_success = bmp280_init(&bmp280_dev, &bmp280_params);
|
bool success = bmp280_init(&bmp280_dev, &bmp280_params);
|
||||||
if (!bmp280_init_success) {
|
bmp280_initialization_required = !success;
|
||||||
// TODO
|
return success;
|
||||||
}
|
|
||||||
|
|
||||||
return bmp280_init_success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bmp280_read(int32_t *temperature_celsius_100, uint32_t *pressure_mbar_100, uint32_t *humidity_percentage_100)
|
bool bmp280_read(int32_t *temperature_celsius_100, uint32_t *pressure_mbar_100, uint32_t *humidity_percentage_100)
|
||||||
|
@ -33,6 +33,7 @@ bool bmp280_read(int32_t *temperature_celsius_100, uint32_t *pressure_mbar_100,
|
||||||
|
|
||||||
bool success = bmp280_read_fixed(&bmp280_dev, &temperature_raw, &pressure_raw, &humidity_raw);
|
bool success = bmp280_read_fixed(&bmp280_dev, &temperature_raw, &pressure_raw, &humidity_raw);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
log_error("BMP280 read failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ bool bmp280_read(int32_t *temperature_celsius_100, uint32_t *pressure_mbar_100,
|
||||||
// Pressure unit is Pascal (= mbar * 100) * 256
|
// Pressure unit is Pascal (= mbar * 100) * 256
|
||||||
*pressure_mbar_100 = (uint32_t) (((float) pressure_raw) / 256.0f);
|
*pressure_mbar_100 = (uint32_t) (((float) pressure_raw) / 256.0f);
|
||||||
}
|
}
|
||||||
|
// NOTE: Only BME280 sensors will report humidity. For BMP280 humidity readings will be zero.
|
||||||
if (humidity_percentage_100) {
|
if (humidity_percentage_100) {
|
||||||
*humidity_percentage_100 = (uint32_t) (((float) humidity_raw) * 100.0f / 1024.0f);
|
*humidity_percentage_100 = (uint32_t) (((float) humidity_raw) * 100.0f / 1024.0f);
|
||||||
}
|
}
|
||||||
|
@ -52,5 +54,39 @@ bool bmp280_read(int32_t *temperature_celsius_100, uint32_t *pressure_mbar_100,
|
||||||
|
|
||||||
bool bmp280_read_telemetry(telemetry_data *data)
|
bool bmp280_read_telemetry(telemetry_data *data)
|
||||||
{
|
{
|
||||||
return bmp280_read(&data->temperature_celsius_100, &data->pressure_mbar_100, &data->humidity_percentage_100);
|
bool success;
|
||||||
|
|
||||||
|
if (bmp280_initialization_required) {
|
||||||
|
log_info("BMP280 re-init\n");
|
||||||
|
success = bmp280_handler_init();
|
||||||
|
log_info("BMP280 re-init: %d\n", success);
|
||||||
|
if (!success) {
|
||||||
|
data->temperature_celsius_100 = 0;
|
||||||
|
data->pressure_mbar_100 = 0;
|
||||||
|
data->humidity_percentage_100 = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success = bmp280_read(&data->temperature_celsius_100, &data->pressure_mbar_100, &data->humidity_percentage_100);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
log_info("BMP280 re-init\n");
|
||||||
|
success = bmp280_handler_init();
|
||||||
|
log_info("BMP280 re-init: %d\n", success);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
success = bmp280_read(&data->temperature_celsius_100, &data->pressure_mbar_100, &data->humidity_percentage_100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
data->temperature_celsius_100 = 0;
|
||||||
|
data->pressure_mbar_100 = 0;
|
||||||
|
data->humidity_percentage_100 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bmp280_initialization_required = !success;
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ size_t horus_packet_v2_create(uint8_t *payload, size_t length, telemetry_data *d
|
||||||
horus_packet.Sats += 200;
|
horus_packet.Sats += 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(horus_packet.CustomData, 0, sizeof(horus_packet.CustomData));
|
||||||
|
|
||||||
uint8_t *custom_data_pointer = horus_packet.CustomData;
|
uint8_t *custom_data_pointer = horus_packet.CustomData;
|
||||||
|
|
||||||
// Unit: cm/s
|
// Unit: cm/s
|
||||||
|
|
11
src/config.h
11
src/config.h
|
@ -11,17 +11,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Set the tracker amateur radio call sign here
|
// Set the tracker amateur radio call sign here
|
||||||
#define CALLSIGN "MYCALL"
|
#define CALLSIGN "OH3VHH"
|
||||||
|
|
||||||
// Disabling LEDs will save power
|
// Disabling LEDs will save power
|
||||||
// Red LED: Lit during initialization and transmit.
|
// Red LED: Lit during initialization and transmit.
|
||||||
// Green LED: Blinking fast when there is no GPS fix. Blinking slowly when the GPS has a fix.
|
// Green LED: Blinking fast when there is no GPS fix. Blinking slowly when the GPS has a fix.
|
||||||
#define LEDS_ENABLE true
|
#define LEDS_ENABLE true
|
||||||
|
|
||||||
|
// Disable LEDs above the specified altitude (in meters) to save power. Set to zero to disable this behavior.
|
||||||
|
#define LEDS_DISABLE_ALTITUDE_METERS 1000
|
||||||
|
|
||||||
// Allow powering off the sonde by pressing the button for over a second (when the sonde is not transmitting)
|
// Allow powering off the sonde by pressing the button for over a second (when the sonde is not transmitting)
|
||||||
#define ALLOW_POWER_OFF false
|
#define ALLOW_POWER_OFF false
|
||||||
|
|
||||||
// Enable use of an externally connected I²C BMP280 atmospheric sensor
|
// Enable use of an externally connected I²C BMP280/BME280 atmospheric sensor
|
||||||
|
// NOTE: Only BME280 sensors will report humidity. For BMP280 humidity readings will be zero.
|
||||||
#define SENSOR_BMP280_ENABLE false
|
#define SENSOR_BMP280_ENABLE false
|
||||||
|
|
||||||
// Enable use of an externally connected I²C Si5351 clock generator chip for HF radio transmissions
|
// Enable use of an externally connected I²C Si5351 clock generator chip for HF radio transmissions
|
||||||
|
@ -36,6 +40,9 @@
|
||||||
// Threshold for time-synchronized modes regarding how far from scheduled transmission time the transmission is still allowed
|
// Threshold for time-synchronized modes regarding how far from scheduled transmission time the transmission is still allowed
|
||||||
#define RADIO_TIME_SYNC_THRESHOLD_MS 2000
|
#define RADIO_TIME_SYNC_THRESHOLD_MS 2000
|
||||||
|
|
||||||
|
// Enable this setting to require 3D fix (altitude required, enable for airborne use), otherwise 2D fix is enough
|
||||||
|
#define GPS_REQUIRE_3D_FIX true
|
||||||
|
|
||||||
// Enable NMEA output from GPS via external serial port. This disables use of I²C bus (Si5351 and sensors) because the pins are shared.
|
// Enable NMEA output from GPS via external serial port. This disables use of I²C bus (Si5351 and sensors) because the pins are shared.
|
||||||
#define GPS_NMEA_OUTPUT_VIA_SERIAL_PORT_ENABLE false
|
#define GPS_NMEA_OUTPUT_VIA_SERIAL_PORT_ENABLE false
|
||||||
|
|
||||||
|
|
|
@ -27,4 +27,7 @@ extern char *aprs_comment_templates[];
|
||||||
extern char *fsq_comment_templates[];
|
extern char *fsq_comment_templates[];
|
||||||
extern char *ftjt_message_templates[];
|
extern char *ftjt_message_templates[];
|
||||||
|
|
||||||
|
void set_green_led(bool enabled);
|
||||||
|
void set_red_led(bool enabled);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -48,6 +48,8 @@
|
||||||
|
|
||||||
#define BMP280_RESET_VALUE 0xB6
|
#define BMP280_RESET_VALUE 0xB6
|
||||||
|
|
||||||
|
#define BMP280_TIMEOUT_COUNTER 0xFFFFF
|
||||||
|
|
||||||
void bmp280_init_default_params(bmp280_params_t *params)
|
void bmp280_init_default_params(bmp280_params_t *params)
|
||||||
{
|
{
|
||||||
params->mode = BMP280_MODE_NORMAL;
|
params->mode = BMP280_MODE_NORMAL;
|
||||||
|
@ -132,6 +134,8 @@ static int write_register8(bmp280 *dev, uint8_t reg, uint8_t value)
|
||||||
|
|
||||||
bool bmp280_init(bmp280 *dev, bmp280_params_t *params)
|
bool bmp280_init(bmp280 *dev, bmp280_params_t *params)
|
||||||
{
|
{
|
||||||
|
uint32_t timeout;
|
||||||
|
|
||||||
if (dev->addr != BMP280_I2C_ADDRESS_0
|
if (dev->addr != BMP280_I2C_ADDRESS_0
|
||||||
&& dev->addr != BMP280_I2C_ADDRESS_1) {
|
&& dev->addr != BMP280_I2C_ADDRESS_1) {
|
||||||
|
|
||||||
|
@ -152,12 +156,16 @@ bool bmp280_init(bmp280 *dev, bmp280_params_t *params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until finished copying over the NVP data.
|
// Wait until finished copying over the NVP data.
|
||||||
while (1) {
|
timeout = BMP280_TIMEOUT_COUNTER;
|
||||||
|
while (timeout-- > 0) {
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
if (read_data(dev, BMP280_REG_STATUS, &status, 1) && (status & 1) == 0) {
|
if (read_data(dev, BMP280_REG_STATUS, &status, 1) && (status & 1) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (timeout == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!read_calibration_data(dev)) {
|
if (!read_calibration_data(dev)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -57,12 +57,16 @@ Si5351::Si5351(i2c_port *port, uint8_t i2c_addr) :
|
||||||
*/
|
*/
|
||||||
bool Si5351::init(uint8_t xtal_load_c, uint32_t xo_freq, int32_t corr)
|
bool Si5351::init(uint8_t xtal_load_c, uint32_t xo_freq, int32_t corr)
|
||||||
{
|
{
|
||||||
|
uint32_t timeout = 0xFFFFFF;
|
||||||
// Wait for SYS_INIT flag to be clear, indicating that device is ready
|
// Wait for SYS_INIT flag to be clear, indicating that device is ready
|
||||||
uint8_t status_reg = 0;
|
uint8_t status_reg = 0;
|
||||||
do {
|
do {
|
||||||
status_reg = si5351_read(SI5351_DEVICE_STATUS);
|
status_reg = si5351_read(SI5351_DEVICE_STATUS);
|
||||||
// TODO: timeout
|
} while (status_reg >> 7 == 1 && timeout-- > 0);
|
||||||
} while (status_reg >> 7 == 1);
|
|
||||||
|
if (timeout == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Set crystal load capacitance
|
// Set crystal load capacitance
|
||||||
si5351_write(SI5351_CRYSTAL_LOAD, (xtal_load_c & SI5351_CRYSTAL_LOAD_MASK) | 0b00010010);
|
si5351_write(SI5351_CRYSTAL_LOAD, (xtal_load_c & SI5351_CRYSTAL_LOAD_MASK) | 0b00010010);
|
||||||
|
|
14
src/gps.h
14
src/gps.h
|
@ -3,12 +3,26 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#define POWER_SAFE_MODE_STATE_ACQUISITION 0
|
#define POWER_SAFE_MODE_STATE_ACQUISITION 0
|
||||||
#define POWER_SAFE_MODE_STATE_TRACKING 1
|
#define POWER_SAFE_MODE_STATE_TRACKING 1
|
||||||
#define POWER_SAFE_MODE_STATE_POWER_OPTIMIZED_TRACKING 2
|
#define POWER_SAFE_MODE_STATE_POWER_OPTIMIZED_TRACKING 2
|
||||||
#define POWER_SAFE_MODE_STATE_INACTIVE 3
|
#define POWER_SAFE_MODE_STATE_INACTIVE 3
|
||||||
|
|
||||||
|
#define GPS_FIX_NO_FIX 0
|
||||||
|
#define GPS_FIX_DEAD_RECKONING_ONLY 1
|
||||||
|
#define GPS_FIX_2D 2
|
||||||
|
#define GPS_FIX_3D 3
|
||||||
|
#define GPS_FIX_GPS_AND_DEAD_RECKONING 4
|
||||||
|
#define GPS_FIX_TIME_ONLY 5
|
||||||
|
|
||||||
|
#if GPS_REQUIRE_3D_FIX
|
||||||
|
#define GPS_HAS_FIX(gps_data) (gps_data.fix_ok && (gps_data.fix == GPS_FIX_3D))
|
||||||
|
#else
|
||||||
|
#define GPS_HAS_FIX(gps_data) (gps_data.fix_ok && (gps_data.fix == GPS_FIX_2D || gps_data.fix == GPS_FIX_3D))
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct _gps_data {
|
typedef struct _gps_data {
|
||||||
bool updated;
|
bool updated;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
#define I2C_TIMEOUT_COUNTER 0x4FFFF
|
||||||
|
|
||||||
struct _i2c_port {
|
struct _i2c_port {
|
||||||
I2C_TypeDef *i2c;
|
I2C_TypeDef *i2c;
|
||||||
};
|
};
|
||||||
|
@ -61,7 +63,7 @@ void i2c_init()
|
||||||
delay_ms(1);
|
delay_ms(1);
|
||||||
}
|
}
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
log_error("ERROR: I²C bus busy during initialization");
|
log_error("ERROR: I²C bus busy during initialization\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
I2C_Cmd(I2C_PORT, ENABLE);
|
I2C_Cmd(I2C_PORT, ENABLE);
|
||||||
|
@ -97,11 +99,11 @@ static void i2c_reset_bus(i2c_port *port)
|
||||||
|
|
||||||
static int i2c_wait_until_not_busy(i2c_port *port)
|
static int i2c_wait_until_not_busy(i2c_port *port)
|
||||||
{
|
{
|
||||||
__IO uint32_t timeout = 0xFFFFFF;
|
__IO uint32_t timeout = I2C_TIMEOUT_COUNTER;
|
||||||
|
|
||||||
while (I2C_GetFlagStatus(I2C_PORT, I2C_FLAG_BUSY)) {
|
while (I2C_GetFlagStatus(I2C_PORT, I2C_FLAG_BUSY)) {
|
||||||
if (--timeout == 0) {
|
if (--timeout == 0) {
|
||||||
log_error("ERROR: Timeout - I2C bus busy");
|
log_error("ERROR: Timeout - I2C bus busy\n");
|
||||||
i2c_reset_bus(port);
|
i2c_reset_bus(port);
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
@ -112,11 +114,11 @@ static int i2c_wait_until_not_busy(i2c_port *port)
|
||||||
|
|
||||||
static bool i2c_wait_event(i2c_port *port, uint32_t flag)
|
static bool i2c_wait_event(i2c_port *port, uint32_t flag)
|
||||||
{
|
{
|
||||||
__IO uint32_t timeout = 0xFFFFFF;
|
__IO uint32_t timeout = I2C_TIMEOUT_COUNTER;
|
||||||
|
|
||||||
while (I2C_CheckEvent(port->i2c, flag) != SUCCESS) {
|
while (I2C_CheckEvent(port->i2c, flag) != SUCCESS) {
|
||||||
if (--timeout == 0) {
|
if (--timeout == 0) {
|
||||||
log_error("ERROR: WE event timeout: 0x%08lx", flag);
|
log_error("ERROR: WE event timeout: 0x%08lx\n", flag);
|
||||||
i2c_reset_bus(port);
|
i2c_reset_bus(port);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -131,13 +133,13 @@ static int i2c_prepare_op(i2c_port *port, uint8_t address)
|
||||||
I2C_GenerateSTART(port->i2c, ENABLE);
|
I2C_GenerateSTART(port->i2c, ENABLE);
|
||||||
|
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_MODE_SELECT)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_MODE_SELECT)) {
|
||||||
log_error("ERROR: PO MMS timeout: 0x%02x", address);
|
log_error("ERROR: PO MMS timeout: 0x%02x\n", address);
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
I2C_Send7bitAddress(port->i2c, address, I2C_Direction_Transmitter);
|
I2C_Send7bitAddress(port->i2c, address, I2C_Direction_Transmitter);
|
||||||
|
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
|
||||||
log_error("ERROR: PO MTMS timeout: 0x%02x", address);
|
log_error("ERROR: PO MTMS timeout: 0x%02x\n", address);
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +155,7 @@ static int i2c_prepare_op_with_register(i2c_port *port, uint8_t address, uint8_t
|
||||||
|
|
||||||
I2C_SendData(port->i2c, reg);
|
I2C_SendData(port->i2c, reg);
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
|
||||||
log_error("ERROR: POWR MBT timeout: 0x%02x 0x%02x", address, reg);
|
log_error("ERROR: POWR MBT timeout: 0x%02x 0x%02x\n", address, reg);
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,13 +171,13 @@ static int i2c_prepare_read(i2c_port *port, uint8_t address, uint8_t reg)
|
||||||
|
|
||||||
I2C_GenerateSTART(port->i2c, ENABLE);
|
I2C_GenerateSTART(port->i2c, ENABLE);
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_MODE_SELECT)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_MODE_SELECT)) {
|
||||||
log_error("ERROR: PR MMS timeout: 0x%02x 0x%02x", address, reg);
|
log_error("ERROR: PR MMS timeout: 0x%02x 0x%02x\n", address, reg);
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
I2C_Send7bitAddress(port->i2c, address, I2C_Direction_Receiver);
|
I2C_Send7bitAddress(port->i2c, address, I2C_Direction_Receiver);
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {
|
||||||
log_error("ERROR: PR MRMS timeout: 0x%02x 0x%02x", address, reg);
|
log_error("ERROR: PR MRMS timeout: 0x%02x 0x%02x\n", address, reg);
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +190,7 @@ static int i2c_finish_read(i2c_port *port)
|
||||||
I2C_AcknowledgeConfig(port->i2c, DISABLE);
|
I2C_AcknowledgeConfig(port->i2c, DISABLE);
|
||||||
|
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
|
||||||
log_error("ERROR: FR MBR timeout");
|
log_error("ERROR: FR MBR timeout\n");
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
I2C_ReceiveData(port->i2c);
|
I2C_ReceiveData(port->i2c);
|
||||||
|
@ -206,7 +208,7 @@ static int i2c_finish_write(i2c_port *port)
|
||||||
I2C_GenerateSTOP(port->i2c, ENABLE);
|
I2C_GenerateSTOP(port->i2c, ENABLE);
|
||||||
|
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
|
||||||
log_error("ERROR: FW MBT timeout");
|
log_error("ERROR: FW MBT timeout\n");
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +229,7 @@ int i2c_read_bytes(i2c_port *port, uint8_t address, uint8_t reg, uint8_t size, u
|
||||||
|
|
||||||
for (uint8_t i = 0; i < size; i++) {
|
for (uint8_t i = 0; i < size; i++) {
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
|
||||||
log_error("ERROR: MBR timeout: 0x%02x 0x%02x", address, reg);
|
log_error("ERROR: MBR timeout: 0x%02x 0x%02x\n", address, reg);
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
data[i] = I2C_ReceiveData(port->i2c);
|
data[i] = I2C_ReceiveData(port->i2c);
|
||||||
|
@ -258,7 +260,7 @@ int i2c_write_bytes(i2c_port *port, uint8_t address, uint8_t reg, uint8_t size,
|
||||||
for (uint8_t i = 0; i < size; i++) {
|
for (uint8_t i = 0; i < size; i++) {
|
||||||
I2C_SendData(port->i2c, data[i]);
|
I2C_SendData(port->i2c, data[i]);
|
||||||
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
|
if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
|
||||||
log_error("ERROR: MBF timeout: 0x%02x 0x%02x", address, reg);
|
log_error("ERROR: MBF timeout: 0x%02x 0x%02x\n", address, reg);
|
||||||
return HAL_ERROR_TIMEOUT;
|
return HAL_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
56
src/main.c
56
src/main.c
|
@ -34,19 +34,37 @@ void handle_timer_tick()
|
||||||
if (leds_enabled) {
|
if (leds_enabled) {
|
||||||
// Blink fast until GPS fix is acquired
|
// Blink fast until GPS fix is acquired
|
||||||
if (counter % (SYSTEM_SCHEDULER_TIMER_TICKS_PER_SECOND / 4) == 0) {
|
if (counter % (SYSTEM_SCHEDULER_TIMER_TICKS_PER_SECOND / 4) == 0) {
|
||||||
if (current_gps_data.fix_ok) {
|
if (GPS_HAS_FIX(current_gps_data)) {
|
||||||
if (counter == 0) {
|
if (counter == 0) {
|
||||||
led_state = !led_state;
|
led_state = !led_state;
|
||||||
system_set_green_led(led_state);
|
set_green_led(led_state);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
led_state = !led_state;
|
led_state = !led_state;
|
||||||
system_set_green_led(led_state);
|
set_green_led(led_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_green_led(bool enabled)
|
||||||
|
{
|
||||||
|
if ((LEDS_DISABLE_ALTITUDE_METERS > 0) && (current_gps_data.altitude_mm / 1000 > LEDS_DISABLE_ALTITUDE_METERS)) {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
system_set_green_led(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_red_led(bool enabled)
|
||||||
|
{
|
||||||
|
if ((LEDS_DISABLE_ALTITUDE_METERS > 0) && (current_gps_data.altitude_mm / 1000 > LEDS_DISABLE_ALTITUDE_METERS)) {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
system_set_red_led(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
|
@ -59,8 +77,8 @@ int main(void)
|
||||||
log_info("System init\n");
|
log_info("System init\n");
|
||||||
system_init();
|
system_init();
|
||||||
|
|
||||||
system_set_green_led(false);
|
set_green_led(false);
|
||||||
system_set_red_led(true);
|
set_red_led(true);
|
||||||
|
|
||||||
if (gps_nmea_output_enabled) {
|
if (gps_nmea_output_enabled) {
|
||||||
log_info("External USART init\n");
|
log_info("External USART init\n");
|
||||||
|
@ -85,13 +103,25 @@ gps_init:
|
||||||
si4032_init();
|
si4032_init();
|
||||||
|
|
||||||
if (bmp280_enabled) {
|
if (bmp280_enabled) {
|
||||||
log_info("BMP280 init\n");
|
for (int i = 0; i < 3; i++) {
|
||||||
bmp280_enabled = bmp280_handler_init();
|
log_info("BMP280 init\n");
|
||||||
|
success = bmp280_handler_init();
|
||||||
|
if (success) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log_error("BMP280 init failed, retrying...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (si5351_enabled) {
|
if (si5351_enabled) {
|
||||||
log_info("Si5351 init\n");
|
for (int i = 0; i < 3; i++) {
|
||||||
si5351_enabled = si5351_handler_init();
|
log_info("Si5351 init\n");
|
||||||
|
success = si5351_handler_init();
|
||||||
|
if (success) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log_error("Si5351 init failed, retrying...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("Radio module init\n");
|
log_info("Radio module init\n");
|
||||||
|
@ -102,11 +132,11 @@ gps_init:
|
||||||
log_info("System initialized!\n");
|
log_info("System initialized!\n");
|
||||||
|
|
||||||
if (leds_enabled) {
|
if (leds_enabled) {
|
||||||
system_set_green_led(true);
|
set_green_led(true);
|
||||||
system_set_red_led(false);
|
set_red_led(false);
|
||||||
} else {
|
} else {
|
||||||
system_set_green_led(false);
|
set_green_led(false);
|
||||||
system_set_red_led(false);
|
set_red_led(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
system_initialized = true;
|
system_initialized = true;
|
||||||
|
|
|
@ -494,7 +494,7 @@ static bool radio_start_transmit(radio_transmit_entry *entry)
|
||||||
log_info("TX start\n");
|
log_info("TX start\n");
|
||||||
|
|
||||||
if (leds_enabled) {
|
if (leds_enabled) {
|
||||||
system_set_red_led(true);
|
set_red_led(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
radio_shared_state.radio_transmission_active = true;
|
radio_shared_state.radio_transmission_active = true;
|
||||||
|
@ -568,7 +568,7 @@ static bool radio_stop_transmit(radio_transmit_entry *entry)
|
||||||
|
|
||||||
usart_gps_enable(true);
|
usart_gps_enable(true);
|
||||||
if (leds_enabled) {
|
if (leds_enabled) {
|
||||||
system_set_red_led(false);
|
set_red_led(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
|
|
@ -33,6 +33,7 @@ bool radio_start_transmit_si5351(radio_transmit_entry *entry, radio_module_state
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: handle Si5351 errors
|
||||||
if (use_fast_si5351) {
|
if (use_fast_si5351) {
|
||||||
si5351_set_drive_strength_fast(SI5351_CLOCK_CLK0, entry->tx_power);
|
si5351_set_drive_strength_fast(SI5351_CLOCK_CLK0, entry->tx_power);
|
||||||
if (set_frequency_early) {
|
if (set_frequency_early) {
|
||||||
|
@ -97,6 +98,7 @@ void radio_handle_main_loop_si5351(radio_transmit_entry *entry, radio_module_sta
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: handle Si5351 errors
|
||||||
if (radio_si5351_state_change) {
|
if (radio_si5351_state_change) {
|
||||||
radio_si5351_state_change = false;
|
radio_si5351_state_change = false;
|
||||||
si5351_set_frequency(SI5351_CLOCK_CLK0, radio_si5351_freq);
|
si5351_set_frequency(SI5351_CLOCK_CLK0, radio_si5351_freq);
|
||||||
|
@ -111,6 +113,7 @@ inline void radio_handle_data_timer_si5351()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: handle Si5351 errors
|
||||||
switch (radio_current_transmit_entry->data_mode) {
|
switch (radio_current_transmit_entry->data_mode) {
|
||||||
case RADIO_DATA_MODE_CW: {
|
case RADIO_DATA_MODE_CW: {
|
||||||
cw_symbol_rate_multiplier--;
|
cw_symbol_rate_multiplier--;
|
||||||
|
|
|
@ -5,9 +5,12 @@
|
||||||
#include "bmp280_handler.h"
|
#include "bmp280_handler.h"
|
||||||
#include "locator.h"
|
#include "locator.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
void telemetry_collect(telemetry_data *data)
|
void telemetry_collect(telemetry_data *data)
|
||||||
{
|
{
|
||||||
|
log_info("Collecting telemetry...\n");
|
||||||
|
|
||||||
data->button_adc_value = system_get_button_adc_value();
|
data->button_adc_value = system_get_button_adc_value();
|
||||||
data->battery_voltage_millivolts = system_get_battery_voltage_millivolts();
|
data->battery_voltage_millivolts = system_get_battery_voltage_millivolts();
|
||||||
data->internal_temperature_celsius_100 = si4032_read_temperature_celsius_100();
|
data->internal_temperature_celsius_100 = si4032_read_temperature_celsius_100();
|
||||||
|
@ -20,7 +23,7 @@ void telemetry_collect(telemetry_data *data)
|
||||||
|
|
||||||
// Zero out position data if we don't have a valid GPS fix.
|
// Zero out position data if we don't have a valid GPS fix.
|
||||||
// This is done to avoid transmitting invalid position information.
|
// This is done to avoid transmitting invalid position information.
|
||||||
if (!data->gps.fix_ok) {
|
if (!GPS_HAS_FIX(data->gps)) {
|
||||||
data->gps.latitude_degrees_1000000 = 0;
|
data->gps.latitude_degrees_1000000 = 0;
|
||||||
data->gps.longitude_degrees_1000000 = 0;
|
data->gps.longitude_degrees_1000000 = 0;
|
||||||
data->gps.altitude_mm = 0;
|
data->gps.altitude_mm = 0;
|
||||||
|
@ -31,4 +34,6 @@ void telemetry_collect(telemetry_data *data)
|
||||||
|
|
||||||
locator_from_lonlat(data->gps.longitude_degrees_1000000, data->gps.latitude_degrees_1000000,
|
locator_from_lonlat(data->gps.longitude_degrees_1000000, data->gps.latitude_degrees_1000000,
|
||||||
LOCATOR_PAIR_COUNT_FULL, data->locator);
|
LOCATOR_PAIR_COUNT_FULL, data->locator);
|
||||||
|
|
||||||
|
log_info("Telemetry collected!\n");
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue