Browse Source

Reworked UI, predicting weather based on p+T

Daniele Lacamera 1 year ago
parent
commit
bc546c7c84
4 changed files with 255 additions and 81 deletions
  1. 1 1
      include/lcd/lcd.h
  2. 7 2
      src/Makefile
  3. 13 13
      src/lcd/lcd.c
  4. 234 65
      src/main.c

+ 1 - 1
include/lcd/lcd.h

@@ -103,7 +103,7 @@ void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 color);
 u32 mypow(u8 m,u8 n);
 void LCD_ShowNum(u16 x,u16 y,u16 num,u8 len,u16 color);
 void LCD_ShowNum1(u16 x,u16 y,float num,u8 len,u16 color);
-void LCD_ShowPicture(u16 x1,u16 y1,u16 x2,u16 y2);
+void LCD_ShowPicture(const char *img, u16 x1,u16 y1,u16 x2,u16 y2);
 void LCD_ShowLogo(void);
 
 

+ 7 - 2
src/Makefile

@@ -10,7 +10,7 @@ LSCRIPT=RISCV/env_Eclipse/GD32VF103xB.lds
 LDFLAGS+=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map -ffreestanding -nostartfiles -fdata-sections -ffunction-sections
 
 
-CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -march=rv32imac -mabi=ilp32 -mcmodel=medlow -fmessage-length=0
+CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -march=rv32imac -mabi=ilp32 -mcmodel=medlow -fmessage-length=0
 CFLAGS+=-Dtimegm=mktime
 #CFLAGS+=--specs=nosys.specs
 CFLAGS+=--specs=nano.specs
@@ -57,7 +57,12 @@ OBJS= \
 	ffunicode.o \
 	tf_card.o \
 	lcd.o \
-	systick.o
+	systick.o \
+	sunny.o \
+	rainy.o \
+	cloudy.o \
+	stormy.o \
+	fair.o
 
 
 all: image.bin

+ 13 - 13
src/lcd/lcd.c

@@ -324,8 +324,14 @@ void Lcd_Init(void)
 	LCD_WR_DATA8(0x0E);
 	LCD_WR_DATA8(0x10);
 
+    /* DLX powersave settings */
+    LCD_WR_REG(0XFC); // Enable Gate power save mode
+    LCD_WR_DATA8(0XC0); // 0XFC[7:6]=GCV_Enable[1:0]=10'b→ Gate Pump Clock Frequency disable
+                                // 0XFC[3:2]=CLK_Variable[1:0]=11'b→ Save Power Ability is Large
+
 	LCD_WR_REG(0x3A);	// define the format of RGB picture data
 	LCD_WR_DATA8(0x05);	// 16-bit/pixel
+                        //
 
 	LCD_WR_REG(0x36);
 	if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x08);
@@ -355,6 +361,8 @@ void LCD_Clear(u16 Color)
 }
 
 
+#if 0
+
 /******************************************************************************
 	   Function description: LCD display Chinese characters
        Entry data: x, y starting coordinates
@@ -387,6 +395,7 @@ void LCD_ShowChinese(u16 x,u16 y,u8 index,u8 size,u16 color)
 		temp++;
 	 }
 }
+#endif
 
 
 /******************************************************************************
@@ -653,24 +662,15 @@ void LCD_ShowNum1(u16 x,u16 y,float num,u8 len,u16 color)
        Entry data: x, y starting point coordinates
        Return value: None
 ******************************************************************************/
-void LCD_ShowPicture(u16 x1,u16 y1,u16 x2,u16 y2)
+void LCD_ShowPicture(const char *img, u16 x1,u16 y1,u16 x2,u16 y2)
 {
 	int i;
+    u32 size = 2 * (1 + x2 - x1) * (1 + y2 - y1); 
 	LCD_Address_Set(x1,y1,x2,y2);
-	for(i=0;i<12800;i++)
+	for(i=0;i<size;i++)
 	{ 	
 		// LCD_WR_DATA8(image[i*2+1]);
-		//LCD_WR_DATA8(image[i]);
-	}			
-}
-
-void LCD_ShowLogo(void)
-{
-	int i;
-	LCD_Address_Set(0,0,159,75);
-	for(i=0;i<25600;i++)
-	{
-		LCD_WR_DATA8(logo_bmp[i]);
+		LCD_WR_DATA8(img[i]);
 	}			
 }
 

+ 234 - 65
src/main.c

@@ -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