|
@@ -4,11 +4,19 @@
|
|
|
#include "gd32vf103_i2c.h"
|
|
|
#include "minmea.h"
|
|
|
|
|
|
+#define MAX_ROW 20
|
|
|
#define BMP180_SOLDERING_OFF_T 190
|
|
|
#define BMP180_SOLDERING_OFF_P 14000
|
|
|
|
|
|
-#define GPS_INTERVAL 3600
|
|
|
+#define FIXED_ALTITUDE 50
|
|
|
+
|
|
|
+extern const char *img_sunny;
|
|
|
+extern const char *img_rainy;
|
|
|
+extern const char *img_stormy;
|
|
|
+extern const char *img_fair;
|
|
|
+extern const char *img_cloudy;
|
|
|
|
|
|
+#ifdef USE_UART0
|
|
|
void init_uart0(void)
|
|
|
{
|
|
|
/* enable GPIO clock */
|
|
@@ -35,6 +43,11 @@ void init_uart0(void)
|
|
|
|
|
|
usart_interrupt_enable(USART0, USART_INT_RBNE);
|
|
|
}
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef USE_GPS
|
|
|
+
|
|
|
+#define GPS_INTERVAL 3600
|
|
|
|
|
|
void init_uart1(void)
|
|
|
{
|
|
@@ -63,8 +76,8 @@ void init_uart1(void)
|
|
|
usart_interrupt_enable(USART1, USART_INT_RBNE);
|
|
|
}
|
|
|
|
|
|
-#define MAX_ROW 20
|
|
|
#define MAX_NMEA 192
|
|
|
+#endif
|
|
|
|
|
|
static inline void i2c_wait_busy(void)
|
|
|
{
|
|
@@ -326,7 +339,23 @@ static uint32_t bmp180_read_P(void)
|
|
|
return (uint32_t)((data_xlsb + (data_lsb << 8) + (data_msb << 16)) >> (8 - BMP180_OSS));
|
|
|
}
|
|
|
|
|
|
+static int64_t time_offset = 0;
|
|
|
+static uint32_t get_today_time(void)
|
|
|
+{
|
|
|
+ uint64_t machine_time = get_timer_value() / (SystemCoreClock >> 2);
|
|
|
+ return (uint32_t)((machine_time % (24 * 3600)) + time_offset);
|
|
|
+}
|
|
|
+
|
|
|
+static void set_today_time(int64_t seconds_since_midnight)
|
|
|
+{
|
|
|
+ uint64_t machine_time = get_timer_value() / (SystemCoreClock >> 2);
|
|
|
+ seconds_since_midnight -= machine_time % (24 * 3600);
|
|
|
+ time_offset = seconds_since_midnight;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
+#ifdef USE_GPS
|
|
|
/* UART/GPS */
|
|
|
|
|
|
static struct minmea_sentence_rmc global_minmea_gps;
|
|
@@ -396,20 +425,6 @@ static int read_gps(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int64_t time_offset = 0;
|
|
|
-static uint32_t get_today_time(void)
|
|
|
-{
|
|
|
- uint64_t machine_time = get_timer_value() / (SystemCoreClock >> 2);
|
|
|
- return (uint32_t)((machine_time % (24 * 3600)) + time_offset);
|
|
|
-}
|
|
|
-
|
|
|
-static void set_today_time(int64_t seconds_since_midnight)
|
|
|
-{
|
|
|
- uint64_t machine_time = get_timer_value() / (SystemCoreClock >> 2);
|
|
|
- seconds_since_midnight -= machine_time % (24 * 3600);
|
|
|
- time_offset = seconds_since_midnight;
|
|
|
-}
|
|
|
-
|
|
|
/* Main */
|
|
|
static void gps_on(void)
|
|
|
{
|
|
@@ -421,39 +436,6 @@ static void gps_off(void)
|
|
|
gpio_bit_write(GPIOA, GPIO_PIN_0, 0);
|
|
|
}
|
|
|
|
|
|
-static void show_pT(void)
|
|
|
-{
|
|
|
- int16_t ut;
|
|
|
- uint32_t up;
|
|
|
- uint32_t pressure;
|
|
|
- int32_t temperature;
|
|
|
- char prs[MAX_ROW]="Pressure";
|
|
|
- char tmp[MAX_ROW]="Temperature";
|
|
|
- ut = bmp180_read_T();
|
|
|
- up = bmp180_read_P();
|
|
|
-
|
|
|
- /* Device offset */
|
|
|
- ut -= BMP180_SOLDERING_OFF_T;
|
|
|
- up -= BMP180_SOLDERING_OFF_P;
|
|
|
-
|
|
|
- temperature = compensate_temperature(ut);
|
|
|
- pressure = compensate_pressure(up);
|
|
|
-
|
|
|
- /* Normalize to sea level if avail */
|
|
|
- if (global_minmea_gps.valid) {
|
|
|
- int32_t gps_altitude = global_minmea_gga.altitude.value /
|
|
|
- global_minmea_gga.altitude.scale;
|
|
|
- pressure += (gps_altitude * 12);
|
|
|
- snprintf(prs, MAX_ROW - 1, "p (sea): %u.%02u", pressure/100, pressure % 100);
|
|
|
- LCD_ShowString(0, 48, (u8 *)(prs), CYAN);
|
|
|
- } else {
|
|
|
- snprintf(prs, MAX_ROW - 1, "p (meas): %u.%02u", pressure/100, pressure % 100);
|
|
|
- LCD_ShowString(0, 48, (u8 *)(prs), MAGENTA);
|
|
|
- }
|
|
|
- snprintf(tmp, MAX_ROW - 1, "T: %d.%d", temperature/10, temperature % 10);
|
|
|
- LCD_ShowString(0, 64, (u8 *)(tmp), GREEN);
|
|
|
-}
|
|
|
-
|
|
|
static int find_gps_fix(void)
|
|
|
{
|
|
|
char gps[MAX_ROW]="GPS Data";
|
|
@@ -502,12 +484,175 @@ static int find_gps_fix(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#endif
|
|
|
+
|
|
|
+enum weather_prediction {
|
|
|
+ SUNNY = 0,
|
|
|
+ FAIR,
|
|
|
+ CLOUDY,
|
|
|
+ RAINY,
|
|
|
+ STORMY,
|
|
|
+};
|
|
|
+
|
|
|
+static void show_weather(enum weather_prediction wp)
|
|
|
+{
|
|
|
+ if (wp == SUNNY)
|
|
|
+ LCD_ShowPicture(img_sunny, 0, 0, 47, 47);
|
|
|
+ if (wp == FAIR)
|
|
|
+ LCD_ShowPicture(img_fair, 0, 0, 47, 47);
|
|
|
+ if (wp == CLOUDY)
|
|
|
+ LCD_ShowPicture(img_cloudy, 0, 0, 47, 47);
|
|
|
+ if (wp == RAINY)
|
|
|
+ LCD_ShowPicture(img_rainy, 0, 0, 47, 47);
|
|
|
+ if (wp == STORMY)
|
|
|
+ LCD_ShowPicture(img_stormy, 0, 0, 47, 47);
|
|
|
+}
|
|
|
+
|
|
|
+static uint32_t p100;
|
|
|
+static int16_t T100;
|
|
|
+static enum weather_prediction CW = FAIR;
|
|
|
+static int32_t weather_delta = 0;
|
|
|
+static uint32_t historic_p = 0;
|
|
|
+static int16_t historic_T = -27400;
|
|
|
+static char weather_desc[MAX_ROW] = "Stable";
|
|
|
+static int weather_color = GREEN;
|
|
|
+
|
|
|
+static void show_ui(void)
|
|
|
+{
|
|
|
+ char prs[MAX_ROW]="Pressure";
|
|
|
+ char tmp[MAX_ROW]="Temperature";
|
|
|
+ char histp[MAX_ROW] = "History";
|
|
|
+ char histT[MAX_ROW] = "History T";
|
|
|
+ char lastrow[MAX_ROW] = "";
|
|
|
+#if 0
|
|
|
+ snprintf(histp, MAX_ROW - 1, "hp: %u.%02u", historic_p/100, historic_p % 100);
|
|
|
+ LCD_ShowString(48, 0, (u8 *)(histp), MAGENTA);
|
|
|
+ snprintf(histT, MAX_ROW - 1, "hT: %d.%d", historic_T/10, historic_T % 10);
|
|
|
+ LCD_ShowString(48, 16, (u8 *)(histT), MAGENTA);
|
|
|
+#endif
|
|
|
+ snprintf(prs, MAX_ROW - 1, "%u.%02u hPa", p100/100, p100 % 100);
|
|
|
+ LCD_ShowString(60, 20, (u8 *)(prs), CYAN);
|
|
|
+ snprintf(tmp, MAX_ROW - 1, " %d.%d C", T100/10, T100 % 10);
|
|
|
+ LCD_ShowString(60, 36, (u8 *)(tmp), GREEN);
|
|
|
+ LCD_ShowString(0, 64, (u8 *)(weather_desc), weather_color);
|
|
|
+ show_weather(CW);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#define SAMPLE_INTERVAL 300
|
|
|
+#define CHANGE_THRESHOLD 100 /* in Pa */
|
|
|
+
|
|
|
+#define HIGH_PRESSURE 102700
|
|
|
+#define CHANGE_PRESSURE 100000
|
|
|
+#define LOW_PRESSURE 99800
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static void predict_weather(void)
|
|
|
+{
|
|
|
+ static enum weather_prediction historic_wp = FAIR;
|
|
|
+ int pdiff, Tdiff;
|
|
|
+ sprintf(weather_desc, "Stable.");
|
|
|
+
|
|
|
+
|
|
|
+ if (historic_p == 0) {
|
|
|
+ historic_p = p100;
|
|
|
+ historic_T = T100;
|
|
|
+ weather_delta = 0;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* First switch current weather by checking high/low average */
|
|
|
+ if (p100 > HIGH_PRESSURE) {
|
|
|
+ sprintf(weather_desc, "Dry.");
|
|
|
+ weather_color = YELLOW;
|
|
|
+ CW = SUNNY;
|
|
|
+ }
|
|
|
+ if (p100 < LOW_PRESSURE) {
|
|
|
+ sprintf(weather_desc, "Wet.");
|
|
|
+ weather_color = CYAN;
|
|
|
+ CW = RAINY;
|
|
|
+ } else if (p100 < CHANGE_PRESSURE) {
|
|
|
+ sprintf(weather_desc, "Low pressure");
|
|
|
+ weather_color = CYAN;
|
|
|
+ CW = CLOUDY;
|
|
|
+ }
|
|
|
+
|
|
|
+ pdiff = p100 - historic_p;
|
|
|
+ Tdiff = T100 - historic_T;
|
|
|
+ weather_delta = 0;
|
|
|
+
|
|
|
+
|
|
|
+ /* p increases, T decreases, or viceversa. Take into account */
|
|
|
+ if (((pdiff > 0) && (Tdiff < 0)) || ((pdiff < 0) && (Tdiff > 0)))
|
|
|
+ {
|
|
|
+ weather_delta = pdiff + ((0 - Tdiff)/10);
|
|
|
+ } else {
|
|
|
+ weather_delta = pdiff;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((weather_delta > 0) && (weather_delta > CHANGE_THRESHOLD)) {
|
|
|
+ sprintf(weather_desc, "Improving.");
|
|
|
+ weather_color = GREEN;
|
|
|
+ if (CW != SUNNY) {
|
|
|
+ CW--;
|
|
|
+ historic_p = p100;
|
|
|
+ historic_T = T100;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if ((weather_delta < 0) && ((0 - weather_delta) > CHANGE_THRESHOLD)) {
|
|
|
+ sprintf(weather_desc, "Worsening.");
|
|
|
+ weather_color = CYAN;
|
|
|
+ if (CW != STORMY) {
|
|
|
+ CW++;
|
|
|
+ historic_p = p100;
|
|
|
+ historic_T = T100;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ historic_p = (63 * historic_p + p100) / 64;
|
|
|
+ historic_T = (63 * historic_T + T100) / 8;
|
|
|
+ }
|
|
|
+ if (weather_delta > 0) {
|
|
|
+ strcat(weather_desc, " (+)");
|
|
|
+ } else if (weather_delta < 0) {
|
|
|
+ strcat(weather_desc, " (-)");
|
|
|
+ } else {
|
|
|
+ strcat(weather_desc, " (=)");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void sample_pT(void)
|
|
|
+{
|
|
|
+ int16_t ut;
|
|
|
+ uint32_t up;
|
|
|
+ uint32_t pressure;
|
|
|
+ int32_t temperature;
|
|
|
+ ut = bmp180_read_T();
|
|
|
+ up = bmp180_read_P();
|
|
|
+
|
|
|
+ /* Device offset */
|
|
|
+ ut -= BMP180_SOLDERING_OFF_T;
|
|
|
+ up -= BMP180_SOLDERING_OFF_P;
|
|
|
+
|
|
|
+ temperature = compensate_temperature(ut);
|
|
|
+ pressure = compensate_pressure(up);
|
|
|
+
|
|
|
+ /* Normalize to sea level */
|
|
|
+ p100 = pressure + FIXED_ALTITUDE * 12;
|
|
|
+ T100 = temperature;
|
|
|
+ predict_weather();
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
int main(void)
|
|
|
{
|
|
|
uint8_t mount_is_ok = 1; /* 0: mount successful ; 1: mount failed */
|
|
|
- char nmea_buf[MAX_NMEA];
|
|
|
- int nmea_i = 0;
|
|
|
uint32_t s_count = 0;
|
|
|
+ int display_on;
|
|
|
+ uint32_t display_on_count = 0;
|
|
|
+ uint32_t display_off_count = 10;
|
|
|
+ const uint32_t sample_interval = 30;
|
|
|
|
|
|
SystemInit();
|
|
|
/* Init GPIOs */
|
|
@@ -518,13 +663,22 @@ int main(void)
|
|
|
/* User Button */
|
|
|
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, GPIO_PIN_8);
|
|
|
|
|
|
+#ifdef USE_GPS
|
|
|
/* GPS on/off */
|
|
|
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_0);
|
|
|
gps_off();
|
|
|
+#endif
|
|
|
+
|
|
|
+ /* User Button */
|
|
|
+ gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, GPIO_PIN_8);
|
|
|
|
|
|
/* HW init: uart, ADC, Display */
|
|
|
+#ifdef USE_UART0
|
|
|
init_uart0();
|
|
|
+#endif
|
|
|
+#ifdef USE_GPS
|
|
|
init_uart1();
|
|
|
+#endif
|
|
|
Lcd_Init();
|
|
|
|
|
|
/* I2C init */
|
|
@@ -533,31 +687,45 @@ int main(void)
|
|
|
/* Read calibration registers */
|
|
|
bmp180_calibrate();
|
|
|
|
|
|
+
|
|
|
+#ifdef USE_GPS
|
|
|
/* Wait for GPS fix */
|
|
|
find_gps_fix();
|
|
|
+#endif
|
|
|
+ sample_pT();
|
|
|
+ LCD_WR_REG(0x10); // Display Off
|
|
|
+ OLED_BLK_Clr();
|
|
|
+ LCD_Clear(BLACK);
|
|
|
|
|
|
/* Main loop */
|
|
|
while (1)
|
|
|
{
|
|
|
- uint64_t time_now = get_today_time();
|
|
|
- char line[MAX_ROW];
|
|
|
- LCD_Clear(BLACK);
|
|
|
-
|
|
|
- snprintf(line, MAX_ROW-1, "t:%02d:%02d:%02d",
|
|
|
- time_now / 3600,
|
|
|
- (time_now % 3600) / 60,
|
|
|
- time_now % 60);
|
|
|
-
|
|
|
- LCD_ShowString (0, 16, (u8 *)line, GREEN);
|
|
|
- show_pT();
|
|
|
- if (s_count++ > GPS_INTERVAL) {
|
|
|
- find_gps_fix();
|
|
|
+ delay_1ms(1000);
|
|
|
+ if (gpio_input_bit_get(GPIOA, GPIO_PIN_8)) {
|
|
|
+ LCD_WR_REG(0x11); // Display On
|
|
|
+ OLED_BLK_Set();
|
|
|
+ display_on = 1;
|
|
|
+ display_on_count = 0;
|
|
|
+ gpio_bit_reset(GPIOB, GPIO_PIN_0);
|
|
|
+ }
|
|
|
+ if (display_on) {
|
|
|
+ show_ui();
|
|
|
+ if (display_on_count++ > display_off_count) {
|
|
|
+ LCD_Clear(BLACK);
|
|
|
+ LCD_WR_REG(0x10); // Display Off
|
|
|
+ OLED_BLK_Clr();
|
|
|
+ display_on = 0;
|
|
|
+ gpio_bit_set(GPIOB, GPIO_PIN_0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(s_count++ >= SAMPLE_INTERVAL) {
|
|
|
s_count = 0;
|
|
|
+ sample_pT();
|
|
|
}
|
|
|
- delay_1ms(1000);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#ifdef USE_UART0
|
|
|
int _put_char(int ch)
|
|
|
{
|
|
|
usart_data_transmit(USART0, (uint8_t) ch );
|
|
@@ -566,3 +734,4 @@ int _put_char(int ch)
|
|
|
|
|
|
return ch;
|
|
|
}
|
|
|
+#endif
|